require_relative 'common' options = get_options(__FILE__) config_path = options['config_path'] ini_path = options['generate_ini_path'] text_path = options['generate_text_path'] code_path = options['generate_code_path'] language = options['source_text_language'] is_generate_field_info = options['generate_field_info'] recreate_dir ini_path recreate_dir text_path recreate_dir code_path require 'csv' # 各类型定义 TypeInfo = Struct.new(:data_type, :data_type_extra, :ref_info, :default_value) FieldInfo = Struct.new(:column_id, :identifier, :comment, :type_info) Table = Struct.new(:csv, :fields, :name2id, :id_field, :raw_name) Ini = Struct.new(:io, :tables) inis = {} # 读取配置表子目录,以形成配置数据目录 Dir["#{config_path}/*"].each do |path| ini_name = File::basename(path) ini = (inis[ini_name] ||= Ini.new(File.open("#{ini_path}/#{ini_name}.ini", 'wb'), {})) next unless File::directory?(path) # 每个配置表子目录将成为一个 ini 文件 # 内含全部子 .csv 表格的导入数据 Dir["#{path}/*.csv"].each do |file| table_name = File::basename(file, '.csv') table = (ini.tables[convert_case(table_name)] = Table.new(csv = CSV.open(file), [], {}, nil, table_name)) identifiers = csv.readline comments = csv.readline type_infos = csv.readline field_id = nil field_id_name = nil # 处理表头列 identifiers.each_with_index do |identifier, index| next if identifier.nil? || identifier.empty? type_info = TypeInfo.new(nil, nil, nil, nil) type_infos[index].gsub(/\s+/, '').scan(/[(:|,|@|=)][a-zA-Z_]+/).each do |info| type_info.data_type = info[1..info.size] if info.start_with?(':') type_info.data_type_extra = info[1..info.size] if info.start_with?(',') type_info.ref_info = convert_case(info[1..info.size]) if info.start_with?('@') type_info.default_value = info[1..info.size] if info.start_with?('=') end field = FieldInfo.new(index, identifier, comments[index], type_info) # 处理特殊类型的字段 case type_info.data_type when 'id' field_id = field next when 'id_name' field_id_name = field next end # 参与导入的条目 table.fields << field end # 验证 Id 列 next if field_id.nil? table.id_field = field_id # 处理条目形成引用表 while !csv.eof? line = csv.readline next if field_id_name.nil? table.name2id[line[field_id_name.column_id]] = line[field_id.column_id].upcase end # 回滚 csv 状态至表头读取后 csv.rewind 3.times { csv.readline } end end # 所有表格缓存 tables = inis.values.collect{|ini| ini.tables}.inject(:merge) # 导入实际数据条目 inis.each_pair do |ini_name, ini_data| register_table = {} enum_table = {} buffer = StringIO.new # 逐目录生成 ini ini_data.tables.each_pair do |table_name, table| register = (register_table[table_name] = []) texts = {} count = 0 # 逐行扫描 while !table.csv.eof? line = table.csv.readline id = line[table.id_field.column_id].upcase buffer.puts "[#{id}]" table.fields.each do |field| value = line[field.column_id] next if value.nil? || value.empty? # 引用名替换处理 if field.type_info.ref_info ref_table = tables[field.type_info.ref_info] value = value.split(',').collect do |ref_name| ref_table.name2id[ref_name] || ref_name.upcase end.join(',') # 数据类型处理 else case field.type_info.data_type # 文本内容 when 'text' index = 0 value = value.split(',').collect do |text| key = "C:#{table_name.upcase}:#{field.column_id}:#{count}" key = "#{key}:#{index}" if index > 0 texts[key] = text index += 1 key end.join(',') # 枚举内容 when 'enum' case field.type_info.data_type_extra # 自动型枚举 when 'auto' enum_key = "#{table_name}#{field.identifier}" value.split(',').each do |v| enums = (enum_table[enum_key] ||= {}) enums[v] = enums.size end end end end buffer.puts "#{field.identifier}=#{value}" count += 1 end buffer.puts register << id end # 导出语言表 if !texts.empty? csf = CSV.open("#{text_path}/#{table.raw_name}.csv", 'wb') csf << ['', language] texts.keys.sort.each do |k| csf << [k, texts[k]] end end end # 导出 ini File.open("#{ini_path}/#{ini_name}.ini", 'wb') do |ini| # 导出注册表 if !register_table.empty? ini.puts '[REGISTER]' register_table.each_pair do |table_name, register| ini.puts "#{table_name}=#{register.join(',')}" end ini.puts end # 导出枚举 if !enum_table.empty? ini.puts '[ENUM]' enum_table.keys.sort.each do |enum_name| ini.puts "#{enum_name}=#{enum_table[enum_name].keys.join(',')}" end ini.puts end # 导出所有条目 ini.puts buffer.string end end