463 lines
14 KiB
Ruby
Executable File
463 lines
14 KiB
Ruby
Executable File
#
|
|
# File:: data_get_usage.rb
|
|
# Description:: Functions for getting the usage of items in a given file.
|
|
#
|
|
# Author:: Marissa Warner-Wu <marissa.warner-wu@rockstarnorth.com>
|
|
# Date:: 22 July 2009
|
|
#
|
|
|
|
#-----------------------------------------------------------------------------
|
|
# Uses
|
|
#-----------------------------------------------------------------------------
|
|
require 'pp'
|
|
require 'pipeline/os/file'
|
|
require 'pipeline/resourcing/path'
|
|
require 'pipeline/projectutil/data_search'
|
|
require 'pipeline/projectutil/data_extract'
|
|
require "rexml/document"
|
|
include REXML
|
|
|
|
#-----------------------------------------------------------------------------
|
|
# Implementation
|
|
#-----------------------------------------------------------------------------
|
|
module Pipeline
|
|
module ProjectUtil
|
|
|
|
#-------------------------------------------------------------------------
|
|
# Functions
|
|
#-------------------------------------------------------------------------
|
|
|
|
#
|
|
# == Description
|
|
# A function for projects with levels which iterates through the objects in a given IDE file and
|
|
# then searches for them in the IPLs using data_get_usage_IPL().
|
|
#
|
|
# Generates a hash which prints to the screen or to an optional output file, if given.
|
|
#
|
|
# === Example Usage
|
|
# Pretty much what it says on the box.
|
|
#
|
|
# ProjectUtil::data_get_usage_IDE( g_Project, g_TargetName, g_OutputFile, g_IDE )
|
|
#
|
|
|
|
def ProjectUtil::data_get_usage_IDE( project, target, outputFile, ide )
|
|
throw ArgumentError.new( "IDE file does not exist (#{ide})." ) unless File.exist?( ide )
|
|
|
|
# Set the level, if needed
|
|
level = ""
|
|
|
|
if true #project.has_levels
|
|
if( OS::Path::get_trailing_directory(ide) == "generic" )
|
|
level = "generic"
|
|
puts "This map has been determined as being generic.\n\n"
|
|
else
|
|
level = OS::Path::get_directories(ide)[-2]
|
|
throw ParseError.new( "Unable to get level name from IDE path." ) if level.empty?
|
|
puts "This map has been determined as being part of the #{level} level.\n\n"
|
|
end
|
|
end #project.has_levels
|
|
|
|
# Get the list of files to search
|
|
files = []
|
|
if level.empty?
|
|
throw RuntimeError.new( "Currently no support for non-leveled projects." )
|
|
else
|
|
files = ProjectUtil::data_find_maps_levels(project, level)
|
|
end
|
|
|
|
# Parse the IDE for objects
|
|
objects = []
|
|
File.open(ide, 'r') do
|
|
text = IO.readlines( ide )
|
|
start = text.index( "objs\n" ) + 1
|
|
finish = text.index( "end\n" ) - 1
|
|
objects = text[start..finish]
|
|
throw ParseError.new( "Unable to parse the IDE." ) if objects.empty?
|
|
end
|
|
|
|
# Print objects and set up the hash
|
|
objects_hash = {}
|
|
objects.each do |line|
|
|
# Parse each line in the list for the object name
|
|
item = line.split(',')[0].downcase
|
|
|
|
# Add item to the hash, values are currently empty arrays
|
|
objects_hash[item] = {}
|
|
end #objects.each
|
|
|
|
# Search the IPLs
|
|
ProjectUtil::data_get_usage_IPL(project, files, objects_hash) do |output_hash|
|
|
if outputFile.empty?
|
|
# If we have no output file, pretty print to the screen
|
|
ObjectUsageHash::pp( output_hash )
|
|
else
|
|
# Otherwise, write to the output file
|
|
puts "\nWriting output to #{outputFile}"
|
|
if OS::Path::get_extension( outputFile ) == "xml"
|
|
ObjectUsageHash::to_xml( outputFile, OS::Path::get_basename(ide), output_hash)
|
|
else
|
|
# Currently we are using ObjectUsageHash::to_txt_by_map(), but we could also use
|
|
# ObjectUsageHash::to_txt_by_ipl() for more detailed output.
|
|
ObjectUsageHash::to_txt_by_map( outputFile, OS::Path::get_basename(ide), output_hash)
|
|
end
|
|
end
|
|
end #data_get_usage_IPL
|
|
|
|
end #data_get_usage_IDE
|
|
|
|
|
|
#
|
|
# == Description
|
|
# A function which takes a hash with object names as keys and a list of files and searches
|
|
# the IPLs in those files for the given objects. The value for each key is given as another
|
|
# hash which gives the object count by map name. The hash then looks like this:
|
|
#
|
|
# { item name => { map name => [[ipl name1, count], [ipl name2, count]] } }
|
|
#
|
|
# Checks both static and streaming IPLs. Yields the updated hash to an optional given block or
|
|
# pretty prints to the screen.
|
|
#
|
|
# === Example Usage
|
|
# Suppose that the item "tools_test" appears 10 times in alp_lake.ipl. We
|
|
# should then get the following from this piece of code:
|
|
#
|
|
# require 'pp'
|
|
# file_list = ["X:\jimmy\build\dev\independent\levels\alpine\alp_lake.ipl"]
|
|
# items = { "tools_test" => [] }
|
|
# ProjectUtil::data_search_IPL(project, file_list, objects_hash) do |myHash|
|
|
# pp myHash
|
|
# end
|
|
# ==> {"tools_test" => {["alp_lake" => [["alp_lake", 10]] } }
|
|
#
|
|
# Getting info from the hash:
|
|
# all_map_info = myHash["tools_test"]
|
|
# map_info = all_map_info["alp_lake"]
|
|
# ipl_info = map_info.assoc("alp_lake")
|
|
# ipl_name = ipl_info[0]
|
|
# count = ipl_info[1]
|
|
#
|
|
def ProjectUtil::data_get_usage_IPL(project, files, objects, &block)
|
|
|
|
# Set variables for extracting img/rpf files
|
|
temp = "X:/temp"
|
|
::FileUtils::rm_r( temp ) if ( ::File::directory?( temp ) )
|
|
r = RageUtils.new( project, project.default_branch )
|
|
|
|
# Go through the list of IPLs
|
|
puts "Checking the following IPLs..."
|
|
files.each do |file|
|
|
# Switch by file extension
|
|
case OS::Path::get_extension( file )
|
|
when "ipl"
|
|
puts OS::Path::get_filename( file )
|
|
ipl_objects = ProjectUtil::data_search_object_in_IPL(file, objects)
|
|
objects = ObjectUsageHash::merge(objects, ipl_objects)
|
|
when "img"
|
|
ProjectUtil::data_extract_image( r, file, temp ) do |extracted_filename|
|
|
if (OS::Path::get_extension( extracted_filename ) == "ipl")
|
|
puts OS::Path::get_filename( extracted_filename )
|
|
ipl_objects = ProjectUtil::data_search_object_in_IPL(extracted_filename, objects)
|
|
objects = ObjectUsageHash::merge(objects, ipl_objects)
|
|
end
|
|
end #data_extract_image
|
|
::FileUtils::rm_r( temp ) if ( ::File::directory?( temp ) )
|
|
when "rpf"
|
|
ProjectUtil::data_extract_rpf( r, file, temp ) do |extracted_filename|
|
|
if (OS::Path::get_extension( extracted_filename ) == "ipl")
|
|
puts OS::Path::get_filename( extracted_filename )
|
|
ipl_objects = ProjectUtil::data_search_object_in_IPL(extracted_filename, objects)
|
|
objects = ObjectUsageHash::merge(objects, ipl_objects)
|
|
end
|
|
end #data_extract_rpf
|
|
::FileUtils::rm_r( temp ) if ::File::directory?( temp )
|
|
end #case OS::Path::get_extension( file )
|
|
end #files.each
|
|
|
|
# If a block is given then yield the object hash, otherwise pretty print it
|
|
if block_given?
|
|
yield( objects )
|
|
else
|
|
ObjectUsageHash::pp( objects )
|
|
end
|
|
|
|
end #data_get_usage_IPL
|
|
|
|
end # ProjectUtil module
|
|
|
|
|
|
#
|
|
# == Description
|
|
# Small class for helper functions which work with the hash object used in data_get_usage_IPL().
|
|
#
|
|
class ObjectUsageHash
|
|
|
|
#---------------------------------------------------------------------
|
|
# Class Methods
|
|
#---------------------------------------------------------------------
|
|
|
|
#
|
|
# == Description
|
|
# A specialised helper function which merges the hash objects used in data_get_usage_IPL().
|
|
# Returns the merged hash.
|
|
#
|
|
# === Example Usage
|
|
# Assumes that the parent hash is one like that received by data_get_usage_IPL(), which contains
|
|
# information for all the maps, and the child hash is one like that generated by data_search_object_in_IPL()
|
|
# which contains only information for a single IPL.
|
|
#
|
|
def ObjectUsageHash::merge(parent_hash, child_hash)
|
|
# Create the new hash for merging
|
|
temp_hash = Hash.new
|
|
new_hash = Hash.new
|
|
|
|
# Go through the child hash
|
|
child_hash.each do |key, value|
|
|
# Pull out the map name
|
|
map_name = ""
|
|
if value[0].include?( "_stream" )
|
|
map_name = value[0].split( "_stream" )[0]
|
|
else
|
|
map_name = value[0]
|
|
end
|
|
|
|
# Update map info
|
|
map_info = parent_hash[key]
|
|
if map_info.has_key?( map_name )
|
|
# If we already have info for this map, add to the existing info
|
|
map_info[map_name] << value
|
|
else
|
|
# Otherwise create new info
|
|
map_info[map_name] = [value]
|
|
end
|
|
|
|
# Construct the new value
|
|
temp_hash[key] = map_info
|
|
end #child_hash.each do
|
|
|
|
# Merge the new values with the parent
|
|
parent_hash.each_key do |key|
|
|
if temp_hash.has_key?( key )
|
|
new_hash[key] = temp_hash[key]
|
|
else
|
|
new_hash[key] = parent_hash[key]
|
|
end
|
|
end
|
|
|
|
#Return the merged hash
|
|
new_hash
|
|
end #merge
|
|
|
|
|
|
#
|
|
# == Description
|
|
# A specialised helper function which pretty prints the Get Usage hash information.
|
|
#
|
|
# === Example Usage
|
|
# Fairly self-explanatory, only really useful for debugging. Usually you would want
|
|
# to print to a file as in below.
|
|
#
|
|
#
|
|
def ObjectUsageHash::pp( usage_hash )
|
|
usage_hash.each do |item, mapInfo|
|
|
puts "---------------- #{item}:"
|
|
pp mapInfo
|
|
end
|
|
end #pp
|
|
|
|
|
|
#
|
|
# == Description
|
|
# A specialised helper function which prints out the Get Usage hash information
|
|
# to a text file.
|
|
#
|
|
# Only prints info by IPL and not by map name.
|
|
#
|
|
# === Example Usage
|
|
# Suppose tools_test is an object in the map alp_test.
|
|
#
|
|
# output_file = "x:/test.txt"
|
|
# map_file = "alp_test"
|
|
# myHash = {"tools_test" => {["alp_lake" => [["alp_lake", 10]] } }
|
|
# ObjectUsageHash::to_txt_by_ipl(output_file, map_file, myHash)
|
|
#
|
|
# This would give you a file x:/test.txt which contains the following:
|
|
# """
|
|
# --- Object usage for alp_test ---
|
|
#
|
|
# --- tools_test:
|
|
# alp_lake - 10
|
|
# """
|
|
#
|
|
#
|
|
def ObjectUsageHash::to_txt_by_ipl( outputFile, mapFile, usage_hash )
|
|
throw ArgumentError.new("No output file given.") if (outputFile.nil? or outputFile.empty?)
|
|
|
|
# Open the output file and start writing
|
|
::FileUtils::rm( outputFile ) if ( File.exist?( outputFile ) )
|
|
log = File.new( outputFile, 'w' )
|
|
log.write( "--- Object usage information for #{mapFile} ---\n\n" )
|
|
|
|
# Alphabetise the output
|
|
key_list = usage_hash.keys
|
|
key_list.sort!
|
|
|
|
# Print info for each item
|
|
key_list.each do |item|
|
|
# Write the item name
|
|
log.write("--- #{item}:\n")
|
|
|
|
# Write the map info
|
|
mapInfo = usage_hash[item]
|
|
if mapInfo.empty?
|
|
log.write("[[UNUSED]]\n")
|
|
else
|
|
mapInfo.each_value do |ipls|
|
|
ipls.each { |iplInfo| log.write("#{iplInfo[0]} - #{iplInfo[1]}\n") }
|
|
end
|
|
end #if mapInfo.empty?
|
|
|
|
log.write("\n")
|
|
end #usage_hash.each
|
|
|
|
log.close()
|
|
end #to_txt_by_ipl
|
|
|
|
|
|
#
|
|
# == Description
|
|
# A specialised helper function which prints out the Get Usage hash information
|
|
# to a text file.
|
|
#
|
|
# Only prints info by map name and not by IPL.
|
|
#
|
|
# === Example Usage
|
|
# Suppose tools_test is an object in the map alp_test.
|
|
#
|
|
# output_file = "x:/test.txt"
|
|
# map_file = "alp_test"
|
|
# myHash = {"tools_test" => {["alp_lake" => [["alp_lake", 10]] } }
|
|
# ObjectUsageHash::to_txt_by_map(output_file, map_file, myHash)
|
|
#
|
|
# This would give you a file x:/test.txt which contains the following:
|
|
# """
|
|
# --- Object usage for alp_test ---
|
|
#
|
|
# --- tools_test:
|
|
# alp_lake - 10
|
|
# """
|
|
#
|
|
#
|
|
def ObjectUsageHash::to_txt_by_map( outputFile, mapFile, usage_hash )
|
|
throw ArgumentError.new("No output file given.") if (outputFile.nil? or outputFile.empty?)
|
|
|
|
# Open the output file and start writing
|
|
::FileUtils::rm( outputFile ) if ( File.exist?( outputFile ) )
|
|
log = File.new( outputFile, 'w' )
|
|
log.write( "--- Object usage information for #{mapFile} ---\n\n" )
|
|
|
|
# Alphabetise the output
|
|
key_list = usage_hash.keys
|
|
key_list.sort!
|
|
|
|
# Print info for each item
|
|
key_list.each do |item|
|
|
# Write the item name
|
|
log.write("--- #{item}:\n")
|
|
|
|
# Write the map info
|
|
mapInfo = usage_hash[item]
|
|
if mapInfo.empty?
|
|
log.write("[[UNUSED]]\n")
|
|
else
|
|
mapInfo.each do |map, ipls|
|
|
count = 0
|
|
ipls.each { |iplInfo| count += iplInfo[1] }
|
|
log.write("#{map} - #{count}\n")
|
|
end
|
|
end #if mapInfo.empty?
|
|
|
|
log.write("\n")
|
|
end #usage_hash.each
|
|
|
|
log.close()
|
|
end #to_txt_by_map
|
|
|
|
|
|
#
|
|
# == Description
|
|
# A specialised helper function which prints out the Get Usage hash information
|
|
# to an XML file.
|
|
#
|
|
# === Example Usage
|
|
# Suppose tools_test is an object in the map alp_test.
|
|
#
|
|
# output_file = "x:/test.xml"
|
|
# map_file = "alp_test"
|
|
# myHash = {"tools_test" => {["alp_lake" => [["alp_lake", 10]] } }
|
|
# ObjectUsageHash::to_xml(output_file, map_file, myHash)
|
|
#
|
|
# This would give you a file x:/test.xml which contains the following content:
|
|
# """
|
|
# <props name="alp_test">
|
|
# <item name="tools_test">
|
|
# <map name="alp_lake">
|
|
# <ipl name="alp_lake" count="10"
|
|
# </map>
|
|
# </item>
|
|
# </props>
|
|
# """
|
|
#
|
|
#
|
|
def ObjectUsageHash::to_xml( outputFile, mapFile, usage_hash )
|
|
throw ArgumentError.new("No output file given.") if (outputFile.nil? or outputFile.empty?)
|
|
|
|
# Open the output file and start writing
|
|
::FileUtils::rm( outputFile ) if ( File.exist?( outputFile ) )
|
|
log = Document.new
|
|
log << XMLDecl.new
|
|
log << Comment.new("Object usage information for #{mapFile}")
|
|
|
|
# Print props file name
|
|
root = Element.new( 'props' )
|
|
root.add_attribute( 'name', mapFile )
|
|
|
|
# Alphabetise the output
|
|
key_list = usage_hash.keys
|
|
key_list.sort!
|
|
|
|
# Print info for each item
|
|
key_list.each do |item|
|
|
# Write the item name
|
|
item_elem = root.add_element( 'item' )
|
|
item_elem.add_attribute( 'name', item )
|
|
|
|
# Write the map info
|
|
mapInfo = usage_hash[item]
|
|
unless mapInfo.empty?
|
|
mapInfo.each do |map, ipls|
|
|
map_elem = item_elem.add_element( 'map' )
|
|
map_elem.add_attribute( 'name', map )
|
|
ipls.each do |iplInfo|
|
|
ipl_elem = map_elem.add_element( 'ipl' )
|
|
ipl_elem.add_attribute( 'name', iplInfo[0] )
|
|
ipl_elem.add_attribute( 'count', iplInfo[1].to_s )
|
|
end
|
|
end #mapInfo.each
|
|
end #if mapInfo.empty?
|
|
end #usage_hash.each
|
|
|
|
log << root
|
|
|
|
# Write the XML
|
|
File.open( outputFile, 'w' ) do |file|
|
|
fmt = REXML::Formatters::Pretty.new()
|
|
fmt.write( log, file )
|
|
end
|
|
|
|
end #to_xml
|
|
|
|
end #ObjectUsageHash class
|
|
|
|
end # Pipeline module
|
|
|
|
# data_get_usage.rb |