From 301f323ee1bb74549fdef1cdf755c65b75d868f8 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Tue, 2 Dec 2025 07:26:19 -0800 Subject: [PATCH] add rake tasks to populate gacha fields from wiki_raw --- lib/tasks/deploy.rake | 204 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) diff --git a/lib/tasks/deploy.rake b/lib/tasks/deploy.rake index a2618d1..431efe1 100644 --- a/lib/tasks/deploy.rake +++ b/lib/tasks/deploy.rake @@ -4,6 +4,210 @@ require_relative '../post_deployment/manager' require_relative '../logging_helper' namespace :deploy do + desc 'Populate all new gacha categorization fields (promotions, season, series). Options: OVERWRITE=true to refresh all' + task populate_gacha_fields: :environment do + puts '=' * 60 + puts 'Populating gacha categorization fields from wiki_raw' + puts '=' * 60 + puts + + # Step 1: Migrate gacha table to promotions arrays (existing data) + puts 'Step 1: Migrating gacha table to promotions arrays...' + Rake::Task['gacha:migrate_promotions'].invoke + puts + + # Step 2: Parse weapons from wiki_raw to fill any gaps + puts 'Step 2: Parsing weapons from wiki_raw...' + Rake::Task['deploy:parse_weapons'].invoke + puts + + # Step 3: Parse summons from wiki_raw to fill any gaps + puts 'Step 3: Parsing summons from wiki_raw...' + Rake::Task['deploy:parse_summons'].invoke + puts + + # Step 4: Parse characters from wiki_raw for season/series/gacha_available + puts 'Step 4: Parsing characters from wiki_raw...' + Rake::Task['deploy:parse_characters'].invoke + puts + + puts '=' * 60 + puts 'Done!' + puts '=' * 60 + end + + desc 'Parse weapons from wiki_raw to populate promotions. Options: OVERWRITE=true' + task parse_weapons: :environment do + overwrite = ENV['OVERWRITE'] == 'true' + + weapons = Weapon.where.not(wiki_raw: [nil, '']) + weapons = weapons.where(promotions: []) unless overwrite + + total = weapons.count + updated = 0 + skipped = 0 + puts " Found #{total} weapons to process#{overwrite ? ' (overwrite mode)' : ''}" + + weapons.find_each.with_index do |weapon, index| + print "\r Processing #{index + 1}/#{total}: #{weapon.name_en.to_s.truncate(40)}".ljust(80) + + obtain = extract_wiki_field(weapon.wiki_raw, 'obtain') + if obtain.blank? + skipped += 1 + next + end + + promotions = promotions_from_obtain(obtain) + if promotions.present? + weapon.update_column(:promotions, promotions) + updated += 1 + end + end + + puts + puts " Updated: #{updated}, Skipped (no obtain): #{skipped}" + end + + desc 'Parse summons from wiki_raw to populate promotions. Options: OVERWRITE=true' + task parse_summons: :environment do + overwrite = ENV['OVERWRITE'] == 'true' + + summons = Summon.where.not(wiki_raw: [nil, '']) + summons = summons.where(promotions: []) unless overwrite + + total = summons.count + updated = 0 + skipped = 0 + puts " Found #{total} summons to process#{overwrite ? ' (overwrite mode)' : ''}" + + summons.find_each.with_index do |summon, index| + print "\r Processing #{index + 1}/#{total}: #{summon.name_en.to_s.truncate(40)}".ljust(80) + + obtain = extract_wiki_field(summon.wiki_raw, 'obtain') + if obtain.blank? + skipped += 1 + next + end + + promotions = promotions_from_obtain(obtain) + if promotions.present? + summon.update_column(:promotions, promotions) + updated += 1 + end + end + + puts + puts " Updated: #{updated}, Skipped (no obtain): #{skipped}" + end + + desc 'Parse characters from wiki_raw to populate season/series/gacha_available. Options: OVERWRITE=true' + task parse_characters: :environment do + overwrite = ENV['OVERWRITE'] == 'true' + + characters = Character.where.not(wiki_raw: [nil, '']) + characters = characters.where(series: [], season: nil) unless overwrite + + total = characters.count + updated = 0 + skipped = 0 + puts " Found #{total} characters to process#{overwrite ? ' (overwrite mode)' : ''}" + + characters.find_each.with_index do |character, index| + print "\r Processing #{index + 1}/#{total}: #{character.name_en.to_s.truncate(40)}".ljust(80) + + wiki_series = extract_wiki_field(character.wiki_raw, 'series') + obtain = extract_wiki_field(character.wiki_raw, 'obtain') + + series = series_from_wiki(wiki_series, obtain, character.wiki_en) + season = season_from_wiki(obtain, character.wiki_en) + gacha_available = gacha_available_from_wiki(wiki_series, obtain) + + if series.present? || season.present? + character.update_columns( + series: series, + season: season, + gacha_available: gacha_available + ) + updated += 1 + else + skipped += 1 + end + end + + puts + puts " Updated: #{updated}, Skipped (no data): #{skipped}" + end + + # Helper methods for parsing wiki_raw + + def extract_wiki_field(wiki_raw, field) + return nil if wiki_raw.blank? + + wiki_raw.each_line do |line| + if line.start_with?("|#{field}=") + return line.sub("|#{field}=", '').strip + end + end + nil + end + + def promotions_from_obtain(obtain) + return [] if obtain.blank? + + mapping = Granblue::Parsers::Wiki.promotions + obtain.downcase.split(',').map(&:strip).filter_map do |value| + mapping[value] + end.uniq.sort + end + + def series_from_wiki(wiki_series, obtain, wiki_en) + series = [] + wiki_en = wiki_en.to_s.downcase + + # Primary series from |series= field + primary = Granblue::Parsers::Wiki.character_series[wiki_series.to_s.downcase.strip] + series << primary if primary + + # Additional from obtain + obtain = obtain.to_s.downcase + series << 2 if obtain.include?('grand') && !series.include?(2) + series << 3 if obtain.include?('zodiac') && !series.include?(3) + + # Seasonal from page name + series << 10 if (wiki_en.include?('summer') || wiki_en.include?('swimsuit')) && !series.include?(10) + series << 11 if wiki_en.include?('yukata') && !series.include?(11) + series << 12 if wiki_en.include?('valentine') && !series.include?(12) + series << 13 if wiki_en.include?('halloween') && !series.include?(13) + series << 14 if wiki_en.include?('formal') && !series.include?(14) + + series.uniq.sort + end + + def season_from_wiki(obtain, wiki_en) + wiki_en = wiki_en.to_s.downcase + obtain = obtain.to_s.downcase + + return 2 if wiki_en.include?('valentine') || obtain.include?('valentine') + return 3 if wiki_en.include?('formal') || obtain.include?('formal') + return 4 if wiki_en.include?('summer') || wiki_en.include?('yukata') || obtain.include?('summer') + return 5 if wiki_en.include?('halloween') || obtain.include?('halloween') + return 6 if wiki_en.include?('holiday') || obtain.include?('holiday') + + # Standard for gacha characters + 1 if obtain.present? && (obtain.include?('premium') || obtain.include?('flash') || obtain.include?('legend')) + end + + def gacha_available_from_wiki(wiki_series, obtain) + wiki_series = wiki_series.to_s.downcase.strip + obtain = obtain.to_s.downcase + + # Non-gacha series + return false if %w[eternal evoker archangel event promo collab].include?(wiki_series) + + # Check obtain for gacha indicators + %w[premium flash legend classic grand zodiac valentine summer halloween holiday formal].any? { |g| obtain.include?(g) } + end + desc 'Post-deployment tasks: Run migrations, import data, download images, and rebuild search indices. Options: TEST=true for test mode, VERBOSE=true for verbose output, STORAGE=local|s3|both' task post_deployment: :environment do include LoggingHelper