Add sigs and docs to transformers

This commit is contained in:
Justin Edmund 2025-01-18 02:16:34 -08:00
parent 0d5d4d5f59
commit 144d860408
7 changed files with 221 additions and 11 deletions

View file

@ -11,7 +11,11 @@ module Granblue
end
end
# Base class for transforming game data into standardized format
# @abstract
class BaseTransformer
# Mapping of game element IDs to internal element IDs
# @return [Hash<Integer, Integer?>]
ELEMENT_MAPPING = {
0 => nil,
1 => 4, # Wind -> Earth
@ -22,6 +26,12 @@ module Granblue
6 => 5 # Light -> Dark
}.freeze
# Initialize a new transformer
# @param data [Object] Raw game data to transform
# @param options [Hash<Symbol, Object>] Optional configuration settings
# @option options [String] :language ('en') Language code for transformations
# @option options [Boolean] :debug (false) Enable debug logging
# @return [void]
def initialize(data, options = {})
@data = data
@options = options
@ -30,6 +40,9 @@ module Granblue
validate_data
end
# Transform the raw data into standardized format
# @abstract Subclasses must implement this method
# @return [Object] Transformed data
def transform
raise NotImplementedError, "#{self.class} must implement #transform"
end
@ -38,6 +51,8 @@ module Granblue
attr_reader :data, :options, :language
# Validate the input data structure
# @return [Boolean] true if valid, false otherwise
def validate_data
Rails.logger.info "[TRANSFORM] Validating data: #{data.inspect[0..100]}..."
@ -55,6 +70,9 @@ module Granblue
true
end
# Extract master and parameter data from an object
# @param obj [Hash<String, Object>] Object containing master/param data
# @return [Array<(Hash?, Hash?)>] Array containing master and param data
def get_master_param(obj)
return [nil, nil] unless obj.is_a?(Hash)
@ -65,6 +83,9 @@ module Granblue
[master, param]
end
# Log a debug message if debug mode is enabled
# @param message [String] Message to log
# @return [void]
def log_debug(message)
return unless options[:debug]
Rails.logger.debug "[TRANSFORM-DEBUG] #{self.class.name}: #{message}"

View file

@ -1,16 +1,41 @@
module Granblue
module Transformers
# Transforms raw game character data into standardized format for database import.
# Handles character stats, uncap levels, transcendence, and perpetuity rings.
#
# @example Transforming character data
# data = { "master" => { "name" => "Katalina", "id" => "3040001000" },
# "param" => { "evolution" => 3, "phase" => 1 } }
# transformer = CharacterTransformer.new(data)
# result = transformer.transform
# # => [{ name: "Katalina", id: "3040001000", uncap: 3, transcend: 1 }]
#
# @note Expects data with "master" and "param" nested objects for each character
# @note Will filter out characters with missing or invalid required attributes
#
# @see BaseTransformer For base transformation functionality
class CharacterTransformer < BaseTransformer
# Transforms raw game character data into a standardized format
# @return [Array<Hash>] Array of character hashes with standardized attributes:
# @option character [String] :name Character's name
# @option character [String] :id Character's ID
# @option character [Integer] :uncap Character's uncap level
# @option character [Boolean] :ringed Whether character has perpetuity rings
# @option character [Integer] :transcend Character's transcendence phase level
def transform
# Log start of transformation process
Rails.logger.info "[TRANSFORM] Starting CharacterTransformer#transform"
# Validate that the input data is a Hash
unless data.is_a?(Hash)
Rails.logger.error "[TRANSFORM] Invalid character data structure"
return []
end
characters = []
# Iterate through each character data entry
data.each_value do |char_data|
# Skip entries missing required master/param data
next unless char_data['master'] && char_data['param']
master = char_data['master']
@ -18,27 +43,29 @@ module Granblue
Rails.logger.debug "[TRANSFORM] Processing character: #{master['name']}"
# Build base character hash with required attributes
character = {
name: master['name'],
id: master['id'],
uncap: param['evolution'].to_i
name: master['name'], # Character's display name
id: master['id'], # Unique identifier
uncap: param['evolution'].to_i # Current uncap level
}
Rails.logger.debug "[TRANSFORM] Base character data: #{character}"
# Add perpetuity (rings) if present
# Add perpetuity ring status if present
if param['has_npcaugment_constant']
character[:ringed] = true
Rails.logger.debug "[TRANSFORM] Character is ringed"
end
# Add transcendence if present
# Add transcendence level if present (stored as 'phase' in raw data)
phase = param['phase'].to_i
if phase && phase.positive?
if phase&.positive?
character[:transcend] = phase
Rails.logger.debug "[TRANSFORM] Character has transcendence: #{phase}"
end
# Only add characters with valid IDs to result set
characters << character unless master['id'].nil?
Rails.logger.info "[TRANSFORM] Successfully processed character #{character[:name]}"
end

View file

@ -2,18 +2,45 @@
module Granblue
module Transformers
# Transforms raw game summon data into standardized format for database import.
# Handles summon stats, uncap levels, transcendence, and quick summon status.
#
# @example Transforming summon data
# data = {
# "master" => { "name" => "Bahamut", "id" => "2040003000" },
# "param" => { "evolution" => 5, "level" => 200 }
# }
# transformer = SummonTransformer.new(data, "2040003000")
# result = transformer.transform
# # => [{ name: "Bahamut", id: "2040003000", uncap: 5, transcend: 1, qs: true }]
#
# @note Expects data with "master" and "param" nested objects for each summon
# @note Handles quick summon status if ID matches provided quick_summon_id
#
# @see BaseTransformer For base transformation functionality
class SummonTransformer < BaseTransformer
# @return [Array<Integer>] Level thresholds for determining transcendence level
TRANSCENDENCE_LEVELS = [210, 220, 230, 240].freeze
# Creates a new summon transformer
# @param data [Object] Raw summon data to transform
# @param quick_summon_id [String, nil] ID of the current quick summon
# @param options [Hash] Additional transformation options
# @option options [String] :language ('en') Language for names
# @option options [Boolean] :debug (false) Enable debug logging
# @return [void]
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
# Transform raw summon data into standardized format
# @return [Array<Hash>] Array of transformed summon data
def transform
Rails.logger.info "[TRANSFORM] Starting SummonTransformer#transform"
# Validate that input data is a Hash
unless data.is_a?(Hash)
Rails.logger.error "[TRANSFORM] Invalid summon data structure"
Rails.logger.error "[TRANSFORM] Data class: #{data.class}"
@ -21,24 +48,27 @@ module Granblue
end
summons = []
# Process each summon in the data
data.each_value do |summon_data|
Rails.logger.debug "[TRANSFORM] Processing summon: #{summon_data['master']['name'] if summon_data['master']}"
# Extract master and parameter data
master, param = get_master_param(summon_data)
unless master && param
Rails.logger.debug "[TRANSFORM] Skipping summon - missing master or param data"
next
end
# Build base summon hash with required attributes
summon = {
name: master['name'],
id: master['id'],
uncap: param['evolution'].to_i
name: master['name'], # Summon's display name
id: master['id'], # Unique identifier
uncap: param['evolution'].to_i # Current uncap level
}
Rails.logger.debug "[TRANSFORM] Base summon data: #{summon}"
# Add transcendence if applicable
# Add transcendence level for highly uncapped summons
if summon[:uncap] > 5
level = param['level'].to_i
trans = calculate_transcendence_level(level)
@ -46,7 +76,7 @@ module Granblue
Rails.logger.debug "[TRANSFORM] Added transcendence level: #{trans}"
end
# Mark quick summon if applicable
# Mark quick summon status if this summon matches quick_summon_id
if @quick_summon_id && param['id'].to_s == @quick_summon_id.to_s
summon[:qs] = true
Rails.logger.debug "[TRANSFORM] Marked as quick summon"
@ -62,6 +92,9 @@ module Granblue
private
# Calculates transcendence level based on summon level
# @param level [Integer, nil] Current summon level
# @return [Integer] Calculated transcendence level (1-5)
def calculate_transcendence_level(level)
return 1 unless level
level = 1 + TRANSCENDENCE_LEVELS.count { |cutoff| level > cutoff }

View file

@ -1,20 +1,47 @@
module Granblue
module Transformers
# Transforms raw game weapon data into standardized format for database import.
# Handles weapon stats, uncap levels, transcendence, awakening, AX skills, and weapon keys.
#
# @example Transforming weapon data
# data = {
# "master" => { "name" => "Luminiera Sword Omega", "id" => "1040007100", "series_id" => 1 },
# "param" => { "level" => 150, "arousal" => { "is_arousal_weapon" => true } }
# }
# transformer = WeaponTransformer.new(data)
# result = transformer.transform
# # => [{ name: "Luminiera Sword Omega", id: "1040007100", uncap: 4, ... }]
#
# @note Expects data with "master" and "param" nested objects for each weapon
# @note Special handling for multi-element weapons from specific series
#
# @see BaseTransformer For base transformation functionality
class WeaponTransformer < BaseTransformer
# @return [Array<Integer>] Level thresholds for determining uncap level
UNCAP_LEVELS = [40, 60, 80, 100, 150, 200].freeze
# @return [Array<Integer>] Level thresholds for determining transcendence level
TRANSCENDENCE_LEVELS = [210, 220, 230, 240].freeze
# @return [Array<Integer>] Weapon series IDs that can have multiple elements
MULTIELEMENT_SERIES = [13, 17, 19].freeze
# Transform raw weapon data into standardized format
# @return [Array<Hash>] Array of transformed weapon data
def transform
# Log start of transformation process
Rails.logger.info "[TRANSFORM] Starting WeaponTransformer#transform"
# Validate that the input data is a Hash
unless data.is_a?(Hash)
Rails.logger.error "[TRANSFORM] Invalid weapon data structure"
return []
end
weapons = []
# Iterate through each weapon entry in the data
data.each_value do |weapon_data|
# Skip entries missing required master/param data
next unless weapon_data['master'] && weapon_data['param']
master = weapon_data['master']
@ -22,18 +49,23 @@ module Granblue
Rails.logger.debug "[TRANSFORM] Processing weapon: #{master['name']}"
# Transform base weapon attributes (ID, name, uncap level, etc)
weapon = transform_base_attributes(master, param)
Rails.logger.debug "[TRANSFORM] Base weapon attributes: #{weapon}"
# Add awakening data if present
weapon.merge!(transform_awakening(param))
Rails.logger.debug "[TRANSFORM] After awakening: #{weapon[:awakening] if weapon[:awakening]}"
# Add AX skills if present
weapon.merge!(transform_ax_skills(param))
Rails.logger.debug "[TRANSFORM] After AX skills: #{weapon[:ax] if weapon[:ax]}"
# Add weapon keys if present
weapon.merge!(transform_weapon_keys(weapon_data))
Rails.logger.debug "[TRANSFORM] After weapon keys: #{weapon[:keys] if weapon[:keys]}"
# Only add weapons with valid IDs
weapons << weapon unless master['id'].nil?
Rails.logger.info "[TRANSFORM] Successfully processed weapon #{weapon[:name]}"
end
@ -44,6 +76,10 @@ module Granblue
private
# Transforms the core weapon attributes from master and param data
# @param master [Hash] Master data containing basic weapon information
# @param param [Hash] Parameter data containing weapon's current state
# @return [Hash] Base weapon attributes including ID, name, uncap level, etc
def transform_base_attributes(master, param)
Rails.logger.debug "[TRANSFORM] Processing base attributes for weapon"
@ -77,6 +113,9 @@ module Granblue
weapon
end
# Transforms weapon awakening data if present
# @param param [Hash] Parameter data containing awakening information
# @return [Hash] Awakening type and level if weapon is awakened
def transform_awakening(param)
return {} unless param['arousal']&.[]('is_arousal_weapon')
@ -89,6 +128,9 @@ module Granblue
}
end
# Transforms AX skill data if present
# @param param [Hash] Parameter data containing AX skill information
# @return [Hash] Array of AX skills with IDs and values
def transform_ax_skills(param)
augments = param['augment_skill_info']
return {} unless augments&.first&.any?
@ -107,6 +149,9 @@ module Granblue
{ ax: ax }
end
# Transforms weapon key data if present
# @param weapon_data [Hash] Full weapon data containing key information
# @return [Hash] Array of weapon key IDs
def transform_weapon_keys(weapon_data)
Rails.logger.debug "[TRANSFORM] Processing weapon keys"
keys = []
@ -122,11 +167,17 @@ module Granblue
keys.any? ? { keys: keys } : {}
end
# Calculates uncap level based on weapon level
# @param level [Integer, nil] Current weapon level
# @return [Integer] Calculated uncap level
def calculate_uncap_level(level)
return 0 unless level
UNCAP_LEVELS.count { |cutoff| level.to_i > cutoff }
end
# Calculates transcendence level based on weapon level
# @param level [Integer, nil] Current weapon level
# @return [Integer] Calculated transcendence level
def calculate_transcendence_level(level)
return 1 unless level
1 + TRANSCENDENCE_LEVELS.count { |cutoff| level.to_i > cutoff }

View file

@ -0,0 +1,31 @@
module Granblue
module Transformers
class TransformerError < StandardError
attr_reader details: untyped
def initialize: (String message, ?untyped details) -> void
end
class BaseTransformer
ELEMENT_MAPPING: Hash[Integer, Integer?]
@data: untyped
@options: Hash[Symbol, untyped]
@language: String
attr_reader data: untyped
attr_reader options: Hash[Symbol, untyped]
attr_reader language: String
def initialize: (untyped data, ?Hash[Symbol, untyped] options) -> void
def transform: -> untyped
def validate_data: -> bool
def get_master_param: (Hash[String, untyped] obj) -> [Hash[String, untyped]?, Hash[String, untyped]?]
def log_debug: (String message) -> void
end
end
end

View file

@ -0,0 +1,20 @@
module Granblue
module Transformers
class SummonTransformer < BaseTransformer
# Level thresholds for transcendence calculations
TRANSCENDENCE_LEVELS: Array[Integer]
# Quick summon ID for the current transformation
@quick_summon_id: String?
def initialize: (untyped data, ?String? quick_summon_id, ?Hash[Symbol, untyped] options) -> void
# Implements abstract method from BaseTransformer
def transform: -> Array[Hash[Symbol, untyped]]
private
def calculate_transcendence_level: (Integer? level) -> Integer
end
end
end

View file

@ -0,0 +1,27 @@
module Granblue
module Transformers
class WeaponTransformer < BaseTransformer
# Constants for level calculations
UNCAP_LEVELS: Array[Integer]
TRANSCENDENCE_LEVELS: Array[Integer]
MULTIELEMENT_SERIES: Array[Integer]
# Implements abstract method from BaseTransformer
def transform: -> Array[Hash[Symbol, untyped]]
private
def transform_base_attributes: (Hash[String, untyped] master, Hash[String, untyped] param) -> Hash[Symbol, untyped]
def transform_awakening: (Hash[String, untyped] param) -> Hash[Symbol, Hash[Symbol, untyped]]
def transform_ax_skills: (Hash[String, untyped] param) -> Hash[Symbol, Array[Hash[Symbol, untyped]]]
def transform_weapon_keys: (Hash[String, untyped] weapon_data) -> Hash[Symbol, Array[String]]
def calculate_uncap_level: (Integer? level) -> Integer
def calculate_transcendence_level: (Integer? level) -> Integer
end
end
end