diff --git a/lib/granblue/transformers/base_deck_transformer.rb b/lib/granblue/transformers/base_deck_transformer.rb new file mode 100644 index 0000000..b6a7faa --- /dev/null +++ b/lib/granblue/transformers/base_deck_transformer.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true + +module Granblue + module Transformers + class BaseDeckTransformer < BaseTransformer + def transform + Rails.logger.info "[TRANSFORM] Starting BaseDeckTransformer#transform" + Rails.logger.info "[TRANSFORM] Data class: #{data.class}" + + # Handle already transformed parameters + if data.is_a?(ActionController::Parameters) && data.key?(:name) + Rails.logger.info "[TRANSFORM] Found existing parameters, returning as is" + return data.to_h.symbolize_keys + end + + # Handle raw game data + Rails.logger.info "[TRANSFORM] Processing raw game data" + input_data = data['import'] if data.is_a?(Hash) + unless input_data + Rails.logger.error "[TRANSFORM] No import data found" + return {} + end + + Rails.logger.info "[TRANSFORM] Found import data" + deck = input_data['deck'] + pc = deck['pc'] if deck + + unless deck && pc + Rails.logger.error "[TRANSFORM] Missing deck or pc data" + Rails.logger.error "[TRANSFORM] deck present: #{!!deck}" + Rails.logger.error "[TRANSFORM] pc present: #{!!pc}" + return {} + end + + Rails.logger.info "[TRANSFORM] Building deck data structure" + result = { + lang: language, + name: deck['name'] || 'Untitled', + class: pc.dig('job', 'master', 'name'), + extra: pc['isExtraDeck'] || false, + subskills: transform_subskills(pc['set_action']), + characters: transform_characters(deck['npc']), + weapons: transform_weapons(pc['weapons']), + summons: transform_summons(pc['summons'], pc['quick_user_summon_id']), + sub_summons: transform_summons(pc['sub_summons']), + friend_summon: pc.dig('damage_info', 'summon_name') + } + + Rails.logger.info "[TRANSFORM] Completed transformation" + Rails.logger.debug "[TRANSFORM] Result: #{result}" + + result + end + + private + + def transform_subskills(set_action) + Rails.logger.info "[TRANSFORM] Processing subskills" + unless set_action.is_a?(Array) && !set_action.empty? + Rails.logger.info "[TRANSFORM] No valid set_action data" + return [] + end + + skills = set_action[0] + unless skills.is_a?(Array) + Rails.logger.info "[TRANSFORM] Invalid skills array" + return [] + end + + results = skills.map { |skill| skill['name'] if skill.is_a?(Hash) }.compact + Rails.logger.info "[TRANSFORM] Found #{results.length} subskills" + results + end + + def transform_characters(npc_data) + Rails.logger.info "[TRANSFORM] Processing characters" + CharacterTransformer.new(npc_data, options).transform + end + + def transform_weapons(weapons_data) + Rails.logger.info "[TRANSFORM] Processing weapons" + WeaponTransformer.new(weapons_data, options).transform + end + + def transform_summons(summons_data, quick_summon_id = nil) + Rails.logger.info "[TRANSFORM] Processing summons" + SummonTransformer.new(summons_data, quick_summon_id, options).transform + end + end + end +end diff --git a/lib/granblue/transformers/base_transformer.rb b/lib/granblue/transformers/base_transformer.rb new file mode 100644 index 0000000..e49a3df --- /dev/null +++ b/lib/granblue/transformers/base_transformer.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +module Granblue + module Transformers + class TransformerError < StandardError + attr_reader :details + + def initialize(message, details = nil) + @details = details + super(message) + end + end + + class BaseTransformer + ELEMENT_MAPPING = { + 0 => nil, + 1 => 4, # Wind -> Earth + 2 => 2, # Fire -> Fire + 3 => 3, # Water -> Water + 4 => 1, # Earth -> Wind + 5 => 6, # Dark -> Light + 6 => 5 # Light -> Dark + }.freeze + + def initialize(data, options = {}) + @data = data + @options = options + @language = options[:language] || 'en' + Rails.logger.info "[TRANSFORM] Initializing #{self.class.name} with data: #{data.class}" + validate_data + end + + def transform + raise NotImplementedError, "#{self.class} must implement #transform" + end + + protected + + attr_reader :data, :options, :language + + def validate_data + Rails.logger.info "[TRANSFORM] Validating data: #{data.inspect[0..100]}..." + + if data.nil? + Rails.logger.info "[TRANSFORM] Data is nil" + return true + end + + if data.empty? + Rails.logger.info "[TRANSFORM] Data is empty" + return true + end + + # Data validation successful + true + end + + def get_master_param(obj) + return [nil, nil] unless obj.is_a?(Hash) + + master = obj['master'] + param = obj['param'] + Rails.logger.debug "[TRANSFORM] Extracted master: #{!!master}, param: #{!!param}" + + [master, param] + end + + def log_debug(message) + return unless options[:debug] + Rails.logger.debug "[TRANSFORM-DEBUG] #{self.class.name}: #{message}" + end + end + end +end diff --git a/lib/granblue/transformers/character_transformer.rb b/lib/granblue/transformers/character_transformer.rb new file mode 100644 index 0000000..210228a --- /dev/null +++ b/lib/granblue/transformers/character_transformer.rb @@ -0,0 +1,51 @@ +module Granblue + module Transformers + class CharacterTransformer < BaseTransformer + def transform + Rails.logger.info "[TRANSFORM] Starting CharacterTransformer#transform" + + unless data.is_a?(Hash) + Rails.logger.error "[TRANSFORM] Invalid character data structure" + return [] + end + + characters = [] + data.each_value do |char_data| + next unless char_data['master'] && char_data['param'] + + master = char_data['master'] + param = char_data['param'] + + Rails.logger.debug "[TRANSFORM] Processing character: #{master['name']}" + + character = { + name: master['name'], + id: master['id'], + uncap: param['evolution'].to_i + } + + Rails.logger.debug "[TRANSFORM] Base character data: #{character}" + + # Add perpetuity (rings) if present + if param['has_npcaugment_constant'] + character[:ringed] = true + Rails.logger.debug "[TRANSFORM] Character is ringed" + end + + # Add transcendence if present + phase = param['phase'].to_i + if phase && phase.positive? + character[:transcend] = phase + Rails.logger.debug "[TRANSFORM] Character has transcendence: #{phase}" + end + + characters << character unless master['id'].nil? + Rails.logger.info "[TRANSFORM] Successfully processed character #{character[:name]}" + end + + Rails.logger.info "[TRANSFORM] Completed processing #{characters.length} characters" + characters + end + end + end +end diff --git a/lib/granblue/transformers/summon_transformer.rb b/lib/granblue/transformers/summon_transformer.rb new file mode 100644 index 0000000..f149c87 --- /dev/null +++ b/lib/granblue/transformers/summon_transformer.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +module Granblue + module Transformers + class SummonTransformer < BaseTransformer + TRANSCENDENCE_LEVELS = [210, 220, 230, 240].freeze + + def initialize(data, quick_summon_id = nil, options = {}) + super(data, options) + @quick_summon_id = quick_summon_id + Rails.logger.info "[TRANSFORM] Initializing SummonTransformer with quick_summon_id: #{quick_summon_id}" + end + + def transform + Rails.logger.info "[TRANSFORM] Starting SummonTransformer#transform" + + unless data.is_a?(Hash) + Rails.logger.error "[TRANSFORM] Invalid summon data structure" + Rails.logger.error "[TRANSFORM] Data class: #{data.class}" + return [] + end + + summons = [] + data.each_value do |summon_data| + Rails.logger.debug "[TRANSFORM] Processing summon: #{summon_data['master']['name'] if summon_data['master']}" + + master, param = get_master_param(summon_data) + unless master && param + Rails.logger.debug "[TRANSFORM] Skipping summon - missing master or param data" + next + end + + summon = { + name: master['name'], + id: master['id'], + uncap: param['evolution'].to_i + } + + Rails.logger.debug "[TRANSFORM] Base summon data: #{summon}" + + # Add transcendence if applicable + if summon[:uncap] > 5 + level = param['level'].to_i + trans = calculate_transcendence_level(level) + summon[:transcend] = trans + Rails.logger.debug "[TRANSFORM] Added transcendence level: #{trans}" + end + + # Mark quick summon if applicable + if @quick_summon_id && param['id'].to_s == @quick_summon_id.to_s + summon[:qs] = true + Rails.logger.debug "[TRANSFORM] Marked as quick summon" + end + + summons << summon + Rails.logger.info "[TRANSFORM] Successfully processed summon #{summon[:name]}" + end + + Rails.logger.info "[TRANSFORM] Completed processing #{summons.length} summons" + summons + end + + private + + def calculate_transcendence_level(level) + return 1 unless level + level = 1 + TRANSCENDENCE_LEVELS.count { |cutoff| level > cutoff } + Rails.logger.debug "[TRANSFORM] Calculated transcendence level: #{level}" + level + end + end + end +end diff --git a/lib/granblue/transformers/transformer_error.rb b/lib/granblue/transformers/transformer_error.rb new file mode 100644 index 0000000..be8b13c --- /dev/null +++ b/lib/granblue/transformers/transformer_error.rb @@ -0,0 +1,12 @@ +module Granblue + module Transformers + class TransformerError < StandardError + attr_reader :details + + def initialize(message, details = nil) + @details = details + super(message) + end + end + end +end diff --git a/lib/granblue/transformers/weapon_transformer.rb b/lib/granblue/transformers/weapon_transformer.rb new file mode 100644 index 0000000..db5e964 --- /dev/null +++ b/lib/granblue/transformers/weapon_transformer.rb @@ -0,0 +1,136 @@ +module Granblue + module Transformers + class WeaponTransformer < BaseTransformer + UNCAP_LEVELS = [40, 60, 80, 100, 150, 200].freeze + TRANSCENDENCE_LEVELS = [210, 220, 230, 240].freeze + MULTIELEMENT_SERIES = [13, 17, 19].freeze + + def transform + Rails.logger.info "[TRANSFORM] Starting WeaponTransformer#transform" + + unless data.is_a?(Hash) + Rails.logger.error "[TRANSFORM] Invalid weapon data structure" + return [] + end + + weapons = [] + data.each_value do |weapon_data| + next unless weapon_data['master'] && weapon_data['param'] + + master = weapon_data['master'] + param = weapon_data['param'] + + Rails.logger.debug "[TRANSFORM] Processing weapon: #{master['name']}" + + weapon = transform_base_attributes(master, param) + Rails.logger.debug "[TRANSFORM] Base weapon attributes: #{weapon}" + + weapon.merge!(transform_awakening(param)) + Rails.logger.debug "[TRANSFORM] After awakening: #{weapon[:awakening] if weapon[:awakening]}" + + weapon.merge!(transform_ax_skills(param)) + Rails.logger.debug "[TRANSFORM] After AX skills: #{weapon[:ax] if weapon[:ax]}" + + weapon.merge!(transform_weapon_keys(weapon_data)) + Rails.logger.debug "[TRANSFORM] After weapon keys: #{weapon[:keys] if weapon[:keys]}" + + weapons << weapon unless master['id'].nil? + Rails.logger.info "[TRANSFORM] Successfully processed weapon #{weapon[:name]}" + end + + Rails.logger.info "[TRANSFORM] Completed processing #{weapons.length} weapons" + weapons + end + + private + + def transform_base_attributes(master, param) + Rails.logger.debug "[TRANSFORM] Processing base attributes for weapon" + + series = master['series_id'].to_i + weapon = { + name: master['name'], + id: master['id'] + } + + # Handle multi-element weapons + if MULTIELEMENT_SERIES.include?(series) + element = master['attribute'].to_i - 1 + weapon[:attr] = element + weapon[:id] = (master['id'].to_i - (element * 100)).to_s + Rails.logger.debug "[TRANSFORM] Multi-element weapon adjustments made" + end + + # Calculate uncap level + level = param['level'].to_i + uncap = calculate_uncap_level(level) + weapon[:uncap] = uncap + Rails.logger.debug "[TRANSFORM] Calculated uncap level: #{uncap}" + + # Add transcendence if applicable + if uncap > 5 + trans = calculate_transcendence_level(level) + weapon[:transcend] = trans + Rails.logger.debug "[TRANSFORM] Added transcendence level: #{trans}" + end + + weapon + end + + def transform_awakening(param) + return {} unless param['arousal']&.[]('is_arousal_weapon') + + Rails.logger.debug "[TRANSFORM] Processing weapon awakening" + { + awakening: { + type: param['arousal']['form_name'], + lvl: param['arousal']['level'] + } + } + end + + def transform_ax_skills(param) + augments = param['augment_skill_info'] + return {} unless augments&.first&.any? + + Rails.logger.debug "[TRANSFORM] Processing AX skills" + ax = [] + augments.first.each_value do |augment| + ax_skill = { + id: augment['skill_id'].to_s, + val: augment['show_value'] + } + ax << ax_skill + Rails.logger.debug "[TRANSFORM] Added AX skill: #{ax_skill}" + end + + { ax: ax } + end + + def transform_weapon_keys(weapon_data) + Rails.logger.debug "[TRANSFORM] Processing weapon keys" + keys = [] + + # Add weapon keys if they exist + ['skill1', 'skill2', 'skill3'].each do |skill_key| + if weapon_data[skill_key]&.[]('id') + keys << weapon_data[skill_key]['id'] + Rails.logger.debug "[TRANSFORM] Added weapon key: #{weapon_data[skill_key]['id']}" + end + end + + keys.any? ? { keys: keys } : {} + end + + def calculate_uncap_level(level) + return 0 unless level + UNCAP_LEVELS.count { |cutoff| level.to_i > cutoff } + end + + def calculate_transcendence_level(level) + return 1 unless level + 1 + TRANSCENDENCE_LEVELS.count { |cutoff| level.to_i > cutoff } + end + end + end +end