hensei-api/app/services/processors/job_processor.rb
Justin Edmund 3cdd925162
Fix filters and add processors (#181)
* Update test csvs

* Fix count filters and refactor apply_filters

* Update party_querying_concern.rb

* +tests/-debug logs

* Make party association optional in Job

* Updates for weapon series

- Change to new series numbers
- Add static method for querying whether the weapon's element is changeable
- Add a new method to return a text slug for the weapon's series

* Add and update test data

- Updates canonical.rb for loading multiple types of data with multiple types of associations
- Adds test data for Guidebooks, Job Accessories, Job Skills, and Jobs
- Updates test data for Weapons and Summons

* Migrations

- Adds series of migrations for changing the weapon's series to the values used by Cygames
- Shuffled around some foreign keys

* Implement BaseProcessor

Processors are in charge of processing deck data straight from Granblue.

* Implement CharacterProcessor

Process character data from deck

* Implement WeaponProcessor

Process weapon data from deck

* Implement JobProcessor

Process job, job skill, and job accessory data from deck

* Implement SummonProcessor

Process summon data from deck

* Update SummonProcessor to work like the others

* ImportController should use processors

* Process element for changeable weapons
2025-02-17 23:51:50 -08:00

127 lines
4.5 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# frozen_string_literal: true
module Processors
##
# JobProcessor is responsible for processing job data from the transformed deck data.
# It finds a Job record by the masters id and assigns it (and its job skills) to the Party.
#
# @example
# raw_data = { 'job' => { "master": { "id": '130401', ... }, ... }, 'set_action': [ ... ] }
# processor = Processors::JobProcessor.new(party, raw_data, language: 'en')
# processor.process
class JobProcessor < BaseProcessor
##
# Initializes a new JobProcessor.
#
# @param party [Party] the Party record.
# @param data [Hash] the raw JSON data.
# @param options [Hash] options hash; e.g. expects :language.
def initialize(party, data, options = {})
super(party, options)
@party = party
@data = data
@language = options[:language] || 'en'
end
##
# Processes job data.
#
# Finds a Job record using a caseinsensitive search on +name_en+ or +name_jp+.
# If found, it assigns the job to the party and (if provided) assigns subskills.
#
# @return [void]
def process
if @data.is_a?(Hash)
@data = @data.with_indifferent_access
else
Rails.logger.error "[JOB] Invalid data format: expected a Hash, got #{@data.class}"
return
end
unless @data.key?('deck') && @data['deck'].key?('pc') && @data['deck']['pc'].key?('job')
Rails.logger.error '[JOB] Missing job data in deck JSON'
return
end
# Extract job data
job_data = @data.dig('deck', 'pc', 'job', 'master')
job_skills = @data.dig('deck', 'pc', 'set_action')
job_accessory_id = @data.dig('deck', 'pc', 'familiar_id') || @data.dig('deck', 'pc', 'shield_id')
# Look up and set the Job and its main skill
process_core_job(job_data)
# Look up and set the job skills.
if job_skills.present?
skills = process_job_skills(job_skills)
party.update(skill1: skills[0], skill2: skills[1], skill3: skills[2])
end
# Look up and set the job accessory.
accessory = process_job_accessory(job_accessory_id)
party.update(accessory: accessory)
rescue StandardError => e
Rails.logger.error "[JOB] Exception during job processing: #{e.message}"
raise e
end
private
##
# Updates the party with the corresponding job and its main skill.
#
# This method attempts to locate a Job using the provided job_data's 'id' (which represents
# the granblue_id). If the job is found, it retrieves the job's main
# skill (i.e. the JobSkill record where `main` is true) and updates the party with the job
# and its main skill. If no job is found, the method returns without updating.
#
# @param [Hash] job_data A hash containing job information.
# It must include the key 'id', which holds the granblue_id for the job.
# @return [void]
#
# @example
# job_data = { 'id' => 42 }
# process_core_job(job_data)
def process_core_job(job_data)
# Look up the Job by granblue_id (the job master id).
job = Job.find_by(granblue_id: job_data['id'])
return unless job
main_skill = JobSkill.find_by(job_id: job.id, main: true)
party.update(job: job, skill0: main_skill)
end
##
# Processes and associates job skills with a given job.
#
# This method first removes any existing skills from the job. It then iterates over the provided
# array of skill names, attempting to find a matching JobSkill record by comparing the provided
# name against both the English and Japanese name fields. Any found JobSkill records are then
# associated with the job. Finally, the method logs the processed job skill names.
#
# @param job_skills [Array<String>] an array of job skill names.
# @return [Array<JobSkill>] an array of JobSkill records that were associated with the job.
def process_job_skills(job_skills)
job_skills.map do |skill|
name = skill['name']
JobSkill.find_by(name_en: name)
end
end
##
# Processes raw data to find the currently set job accessory
#
# Searches JobAccessories for the given `granblue_id`
#
# @param accessory_id [String] the granblue_id of the accessory
def process_job_accessory(accessory_id)
JobAccessory.find_by(granblue_id: accessory_id)
end
# Converts a value (string or boolean) to a boolean.
def to_boolean(val)
val.to_s.downcase == 'true'
end
end
end