diff --git a/app/lib/presenter.rb b/app/lib/presenter.rb index bce12048..1e94884e 100644 --- a/app/lib/presenter.rb +++ b/app/lib/presenter.rb @@ -45,8 +45,12 @@ def self.normalized_screen_name(screen_name) end def self.formatted_product_names_for_tweet(character_name) + return '' if Character.find_by(name: character_name).blank? + products = Character.find_by(name: character_name).products + return '' if products.blank? + product_name_long_to_short = { '幻想水滸伝' => 'I', '幻想水滸伝II' => 'II', diff --git a/app/models/counting_all_character.rb b/app/models/counting_all_character.rb index 6f655c62..5ab72fa2 100644 --- a/app/models/counting_all_character.rb +++ b/app/models/counting_all_character.rb @@ -11,7 +11,7 @@ class CountingAllCharacter < ApplicationRecord scope :by_tweet, -> { where(vote_method: :by_tweet) } scope :by_dm, -> { where(vote_method: :by_direct_message) } - enum vote_method: { by_tweet: 0, by_direct_message: 1, by_others: 99 }, _prefix: true + enum vote_method: { by_tweet: 0, by_direct_message: 1, op_cl_illustrations_bonus: 2, by_others: 99 }, _prefix: true def self.tweets_whose_invisible_status_is_different_between_sheet_and_database sheet_invisible_tweet_ids = CountingAllCharacter.invisible.pluck(:tweet_id) @@ -28,9 +28,10 @@ def self.tweets_whose_invisible_status_is_different_between_sheet_and_database # キャラの数え上げには SQL を使わずに個数を愚直に数える方法を採る def self.all_character_names_including_duplicated - chara_1_column_characters = CountingAllCharacter.valid_records.pluck(:chara_1) - chara_2_column_characters = CountingAllCharacter.valid_records.pluck(:chara_2) - chara_3_column_characters = CountingAllCharacter.valid_records.pluck(:chara_3) + # オールキャラではさらに統合集計が必要なので「ボ・OP・CLイラスト(協力攻撃)」は除外している + chara_1_column_characters = CountingAllCharacter.valid_records.where.not(vote_method: :op_cl_illustrations_bonus).pluck(:chara_1) + chara_2_column_characters = CountingAllCharacter.valid_records.where.not(vote_method: :op_cl_illustrations_bonus).pluck(:chara_2) + chara_3_column_characters = CountingAllCharacter.valid_records.where.not(vote_method: :op_cl_illustrations_bonus).pluck(:chara_3) (chara_1_column_characters + chara_2_column_characters + chara_3_column_characters).compact_blank.sort end diff --git a/app/models/counting_bonus_vote.rb b/app/models/counting_bonus_vote.rb index f874e887..bfebc3cd 100644 --- a/app/models/counting_bonus_vote.rb +++ b/app/models/counting_bonus_vote.rb @@ -13,13 +13,200 @@ class CountingBonusVote < ApplicationRecord enum vote_method: { by_tweet: 0, by_direct_message: 1, by_others: 99 }, _prefix: true enum bonus_category: { - op_cl_illustrations: 0, + op_cl_illustrations: 0, # 未使用 short_stories: 1, - result_illustrations: 2, + result_illustrations: 2, # 未使用 fav_quotes: 3, sosenkyo_campaigns: 4 }, _prefix: true + def self.ranking_short_stories + base_records = CountingBonusVote.valid_records.where(bonus_category: :short_stories) + + ranking_records = [] + + base_records.each do |record| + url = record.tweet.blank? ? '' : record.tweet.url + id_on_sheet = record.id_on_sheet + vote_method = record.vote_method + theme = record.short_stories_theme + contents = record.contents + chara_names = [ + record.chara_01, record.chara_02, record.chara_03, record.chara_04, + record.chara_05, record.chara_06, record.chara_07, record.chara_08, + record.chara_09, record.chara_10 + ].compact_blank.sort.reject { |el| el == "FALSE"} + + chara_names.each do |chara_name| + ranking_records << { + url: url, + id_on_sheet: id_on_sheet, + vote_method: vote_method, + theme: theme, + contents: contents, + character_name: chara_name + } + end + end + + ranking_records.sort_by do |element| + [element[:character_name]] + end + end + + def self.ranking_fav_quotes + base_records = CountingBonusVote.valid_records.where(bonus_category: :fav_quotes) + chara_columns = %i[ + chara_01 chara_02 chara_03 chara_04 chara_05 + chara_06 chara_07 chara_08 chara_09 chara_10 + ] + + ranking_records = [] + + base_records.each do |record| + id_on_sheet = record.id_on_sheet + url = record.tweet.blank? ? '' : record.tweet.url + vote_method = record.vote_method + contents = record.contents + character_names = chara_columns.map { |c| record[c] }.compact_blank.reject { |el| el == "FALSE"} + + # キャラが複数いる場合には分割する(一キャラ一台詞一レコード) + # この分割の結果、ツイート人数(DM人数)とキャラレコード数が一致しなくなることに注意する + character_names.each do |character_name| + ranking_records << { + id_on_sheet: id_on_sheet, + url: url, + vote_method: vote_method, + contents: contents, + character_name: character_name + } + end + end + + ranking_records.sort_by do |element| + [element[:character_name]] + end + end + + def self.ranking_result_illustrations + base_records = OnRawSheetResultIllustrationTotalling.all.reject do |record| + record.character_name_by_sheet_totalling.start_with?('TEMP_') + end + + ranking_records = [] + + base_records.each do |record| + ranking_records << { + name: record.character_name_by_sheet_totalling, + number_of_applications: record.number_of_applications + } + end + + ranking_records.sort_by do |element| + [ + element[:name], element[:number_of_applications] + ] + end + end + + def self.ranking_op_cl_illustrations + all_characters_base_records = CountingAllCharacter.where(vote_method: :op_cl_illustrations_bonus) + all_characters_ranking_records = [] + all_characters_base_records.each do |record| + all_characters_ranking_records << { + chara_1: record.chara_1 + } + end + + unite_attacks_ranking_records = [] + unite_attacks_base_records = CountingUniteAttack.where(vote_method: :op_cl_illustrations_bonus) + unite_attacks_base_records.each do |record| + unite_attacks_ranking_records << { + product_name: record.product_name, + unite_attack_name: record.unite_attack_name + } + end + + { + all_characters: all_characters_ranking_records, + unite_attacks: unite_attacks_ranking_records + } + end + + def self.ranking_sosenkyo_campaigns + base_records = CountingBonusVote.valid_records.where(bonus_category: :sosenkyo_campaigns) + + chara_columns = %i[ + chara_01 chara_02 chara_03 chara_04 chara_05 + chara_06 chara_07 chara_08 chara_09 chara_10 + chara_11 chara_12 + ] + ranking_records = [] + + base_records.each do |record| + url = record.tweet.blank? ? '' : record.tweet.url + id_on_sheet = record.id_on_sheet + vote_method = record.vote_method + contents = record.contents + + character_names = chara_columns.map { |c| record[c] }.compact_blank.reject { |el| el == "FALSE"} + + character_names.each do |character_name| + ranking_records << { + url: url, + id_on_sheet: id_on_sheet, + vote_method: vote_method, + contents: contents, + character_name: character_name + } + end + end + + ranking_records.sort_by do |element| + [element[:character_name]] + end + end + + # category_name は書き込み対象のシートを指している(名前が良くないので変えるべき) + # 書き込み対象のシートによって何を書き込むかが異なるので、base_records がいろいろ変わる + # base_records のソースが必ずしも CountingBonusVote のレコードであるとは限らない + def self.ranking(written_sheet_name) + return unless written_sheet_name.in?( + [ + 'ボ・お題小説', + 'ボ・推し台詞', + 'ボ・開票イラスト', + 'ボ・選挙運動', + 'ボ・OP・CLイラスト(オールキャラ)', + ] + ) + + if written_sheet_name.in?(['ボ・推し台詞']) + base_records = CountingBonusVote.valid_records.where(bonus_category: :fav_quotes) + chara_columns = %i[chara_01 chara_02 chara_03 chara_04 chara_05 chara_06 chara_07 chara_08 chara_09 chara_10] + ret_array = [] + + base_records.each do |record| + character_names = chara_columns.map { |c| record[c] } + character_names = character_names.compact_blank.reject { |el| el == "FALSE"} + + # キャラが複数いる場合には分割する(一キャラ一台詞一レコード) + # この分割の結果、ツイート人数(DM人数)とキャラレコード数が一致しなくなることに注意する + character_names.each do |character_name| + inserted_hash = {} + + inserted_hash[:vote_method] = record.vote_method + inserted_hash[:character_name] = character_name + + ret_array << inserted_hash + end + end + + return ret_array + end + end + + # 「推し台詞」 def self.all_fav_quote_character_names_including_duplicated chara_columns = %i[chara_01 chara_02 chara_03 chara_04 chara_05 chara_06 chara_07 chara_08 chara_09 chara_10] character_names = [] @@ -28,8 +215,7 @@ def self.all_fav_quote_character_names_including_duplicated character_names += CountingBonusVote.valid_records.where(bonus_category: :fav_quotes).pluck(column) end - # TODO: compact_blank が使えるはず - character_names.compact.reject(&:empty?).sort + character_names.compact_blank.sort end def self.fav_quote_character_name_to_number_of_votes @@ -40,6 +226,7 @@ def self.fav_quote_ranking_style Presenter::Counting.key_to_rank_number_by_sosenkyo_style(fav_quote_character_name_to_number_of_votes) end + # 「お題小説」 def short_stories_theme return 'そういえば' if tweet&.id_number == 1541078991146467329 # 例外的な処理 @@ -47,7 +234,7 @@ def short_stories_theme pickuped_theme_names = ['記念', 'そういえば', 'フリー', 'その他'] - # NOTE: 一般的な記述の中に「お題」の語句が含まれていると誤判定する + # NOTE: 一般的な記述の中に「お題」の語句が含まれていると誤判定してしまうので注意する this_theme = pickuped_theme_names.find do |theme| contents.include?(theme) end @@ -56,4 +243,13 @@ def short_stories_theme 'その他' => 'フリー' }[this_theme] || this_theme end + + def contents_resource + case vote_method + when 'by_tweet' + tweet + when 'by_direct_message' + direct_message + end + end end diff --git a/app/models/counting_unite_attack.rb b/app/models/counting_unite_attack.rb index 12f38645..28d45982 100644 --- a/app/models/counting_unite_attack.rb +++ b/app/models/counting_unite_attack.rb @@ -17,10 +17,10 @@ class CountingUniteAttack < ApplicationRecord scope :by_tweet, -> { where(vote_method: :by_tweet) } scope :by_dm, -> { where(vote_method: :by_direct_message) } - enum vote_method: { by_tweet: 0, by_direct_message: 1, by_others: 99 }, _prefix: true + enum vote_method: { by_tweet: 0, by_direct_message: 1, op_cl_illustrations_bonus: 2, by_others: 99 }, _prefix: true - def self.full_ranking - group(:product_name, :unite_attack_name).having('unite_attack_name is not null').order('count_all desc').count + def self.ranking + group(:product_name, :unite_attack_name, :kana).having('unite_attack_name is not null').order('count_all desc').count end def self.product_name_ranking @@ -42,8 +42,7 @@ def self.invalid_records_whose_product_name_is_incorrect # 不正レコードのチェッカ def self.invalid_records_whose_attack_name_is_incorrect - # TODO: compact_blank が使えるはず - correct_attack_names = OnRawSheetUniteAttack.pluck(:name, :name_en).flatten.reject(&:empty?) + correct_attack_names = OnRawSheetUniteAttack.pluck(:name, :name_en).flatten.compact_blank invalid_records = [] diff --git a/app/models/user.rb b/app/models/user.rb index 8051de13..ff313199 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -47,8 +47,7 @@ def all_counting_records end def on_all_character_division_all_character_names - # TODO: compact_blank が使えるはず - counting_all_characters.map(&:three_chara_names).flatten.compact.reject(&:empty?) + counting_all_characters.map(&:three_chara_names).flatten.compact_blank end def on_all_character_division_voting_over_three? @@ -58,4 +57,18 @@ def on_all_character_division_voting_over_three? def on_all_character_division_voting_to_the_same_characters? on_all_character_division_all_character_names.size != on_all_character_division_all_character_names.uniq.size end + + def all_tweets_and_dms + all_characters_tweets = counting_all_characters.valid_records + unite_attacks_tweets = counting_unite_attacks.valid_records + bonus_votes_tweets = counting_bonus_votes.valid_records + dms = direct_messages # DM の性質上、valid_records のスコープは無い + + { + all_characters_tweets: all_characters_tweets, + unite_attacks_tweets: unite_attacks_tweets, + bonus_votes_tweets: bonus_votes_tweets, + dms: dms + } + end end diff --git a/app/services/sheets/counting/all_characters.rb b/app/services/sheets/counting/all_characters.rb index 2565a626..043a2d3d 100644 --- a/app/services/sheets/counting/all_characters.rb +++ b/app/services/sheets/counting/all_characters.rb @@ -60,7 +60,7 @@ def self.import_via_tweet '[DONE] Sheets::Counting::AllCharacters.import_via_tweet' end - def self.import_via_dm + def self.import_via_dm # rubocop:disable Metrics/MethodLength sheet_names = YAML.load_file(Rails.root.join('config/counting_sheet_names.yml'))['names'] # rubocop:disable Metrics/BlockLength @@ -91,28 +91,29 @@ def self.import_via_dm input_10: row[22] } - # DMの書式が自由すぎるので、こちらで条件を吸収する - next if column_vs_value[:category] != '①オールキャラ部門' && column_vs_value[:category] != '両部門' + next unless column_vs_value[:category].in?(['①オールキャラ部門', '両部門', 'ボ・OP・CLイラスト']) next if column_vs_value[:is_invisible] == 'TRUE' || column_vs_value[:is_out_of_counting] == 'TRUE' next if column_vs_value[:id_on_sheet].blank? || column_vs_value[:dm_id_number].blank? || column_vs_value[:contents].blank? dm = DirectMessage.find_by(id_number: column_vs_value[:dm_id_number]) dm_id = dm&.id - # NOTE: dm&.user は不要としてもいい + # NOTE: dm&.user は実質不要っぽい user = dm&.user || create_or_find_by_user(column_vs_value) user_id = user&.id + this_vote_method = column_vs_value[:category] == 'ボ・OP・CLイラスト' ? :op_cl_illustrations_bonus : :by_direct_message + unique_attrs = { id_on_sheet: column_vs_value[:id_on_sheet], user_id: user_id, - vote_method: :by_direct_message, + vote_method: this_vote_method, direct_message_id: dm_id, other_tweet_ids_text: nil, contents: column_vs_value[:contents] } - # 「両部門の場合は、N列とO列に協力攻撃、P列Q列R列にオールキャラ部門を入力する」という例外規定 + # カテゴリごとにキャラ名が入っている列が異なる(もっときれいに書きたい) case column_vs_value[:category] when '①オールキャラ部門' chara_1 = column_vs_value[:input_01] @@ -122,6 +123,8 @@ def self.import_via_dm chara_1 = column_vs_value[:input_03] chara_2 = column_vs_value[:input_04] chara_3 = column_vs_value[:input_05] + when 'ボ・OP・CLイラスト' + chara_1 = column_vs_value[:input_03] end mutable_attrs = { diff --git a/app/services/sheets/counting/bonus_votes.rb b/app/services/sheets/counting/bonus_votes.rb index 2d864aee..e01d79f5 100644 --- a/app/services/sheets/counting/bonus_votes.rb +++ b/app/services/sheets/counting/bonus_votes.rb @@ -7,7 +7,7 @@ def self.import_via_tweet bonus_category_to_sheet_id.each do |bonus_category, this_sheet_id| next if this_sheet_id.blank? - rows = SheetData.get_rows(sheet_id: this_sheet_id, range: "#{sheet_names[i]}!A2:Q101") + rows = SheetData.get_rows(sheet_id: this_sheet_id, range: "#{sheet_names[i]}!A2:Z101") rows.each do |row| column_vs_value = column_vs_value(row) @@ -41,7 +41,9 @@ def self.import_via_tweet chara_07: column_vs_value[:input_07], chara_08: column_vs_value[:input_08], chara_09: column_vs_value[:input_09], - chara_10: column_vs_value[:input_10] + chara_10: column_vs_value[:input_10], + chara_11: column_vs_value[:input_11], + chara_12: column_vs_value[:input_12] } CountingBonusVote.find_or_initialize_by(unique_attrs).update!(mutable_attrs) @@ -56,7 +58,7 @@ def self.import_via_tweet def self.import_via_dm ActiveRecord::Base.transaction do sheet_names.each_with_index do |sheet_name, i| - rows = SheetData.get_rows(sheet_id: ENV.fetch('COUNTING_DIRECT_MESSAGES_SHEET_ID', nil), range: "#{sheet_names[i]}!A2:Q101") + rows = SheetData.get_rows(sheet_id: ENV.fetch('COUNTING_DIRECT_MESSAGES_SHEET_ID', nil), range: "#{sheet_names[i]}!A2:Z101") rows.each do |row| dm_column_vs_value = dm_column_vs_value(row) @@ -185,7 +187,9 @@ def self.column_vs_value(row) input_07: row[20], input_08: row[21], input_09: row[22], - input_10: row[23] + input_10: row[23], + input_11: row[24], + input_12: row[25] } end diff --git a/app/services/sheets/counting/unite_attacks.rb b/app/services/sheets/counting/unite_attacks.rb index b0b02a33..4aafce95 100644 --- a/app/services/sheets/counting/unite_attacks.rb +++ b/app/services/sheets/counting/unite_attacks.rb @@ -67,7 +67,7 @@ def self.import_via_tweet def self.import_via_dm sheet_names = YAML.load_file(Rails.root.join('config/counting_sheet_names.yml'))['names'] - ActiveRecord::Base.transaction do + ActiveRecord::Base.transaction do # rubocop:disable Metrics/BlockLength sheet_names.each_with_index do |sheet_name, i| rows = SheetData.get_rows(sheet_id: ENV.fetch('COUNTING_DIRECT_MESSAGES_SHEET_ID', nil), range: "#{sheet_names[i]}!A2:Q101") @@ -94,24 +94,32 @@ def self.import_via_dm input_10: row[22] } - next if column_vs_value[:category] != '②協力攻撃部門' || column_vs_value[:category] != '両部門' + next unless column_vs_value[:category].in?(['②協力攻撃部門', '両部門', 'ボ・OP・CLイラスト']) next if column_vs_value[:id_on_sheet].blank? || column_vs_value[:dm_id_number].blank? || column_vs_value[:contents].blank? dm = DirectMessage.find_by(id_number: column_vs_value[:dm_id_number]) - dm_id = dm.id - user_id = dm.user.id + + if dm.present? + dm_id = dm.id + user_id = dm.user.id + else + dm_id = nil + user = create_or_find_by_user(column_vs_value) + user_id = user.id + end + + this_vote_method = column_vs_value[:category] == 'ボ・OP・CLイラスト' ? :op_cl_illustrations_bonus : :by_direct_message unique_attrs = { id_on_sheet: column_vs_value[:id_on_sheet], user_id: user_id, - vote_method: :by_direct_message, + vote_method: this_vote_method, direct_message_id: dm_id, other_tweet_ids_text: nil, contents: column_vs_value[:contents] } - # 「両部門の場合は、N列とO列に協力攻撃、P列Q列R列にオールキャラ部門を入力する」という例外規定 mutable_attrs = { is_invisible: column_vs_value[:is_invisible].to_boolean, is_out_of_counting: column_vs_value[:is_out_of_counting].to_boolean, diff --git a/app/services/sheets/write_and_update/final_results/bonus_votes/base.rb b/app/services/sheets/write_and_update/final_results/bonus_votes/base.rb new file mode 100644 index 00000000..c95deab0 --- /dev/null +++ b/app/services/sheets/write_and_update/final_results/bonus_votes/base.rb @@ -0,0 +1,128 @@ +module Sheets + module WriteAndUpdate + module FinalResults + module BonusVotes + class Base + REQUIRED_SHEET_NAMES = [ + 'ボ・お題小説', + 'ボ・推し台詞', + 'ボ・開票イラスト', + 'ボ・選挙運動', + 'ボ・OP・CLイラスト(オールキャラ)', + 'ボ・OP・CLイラスト(協力攻撃)', # 未使用 + ].freeze + + def initialize + @sheet_name = this_sheet_name + + return unless @sheet_name.in?(REQUIRED_SHEET_NAMES) + + @column_name_to_index_hash = this_column_name_to_index_hash + end + + def exec + # written_sheet_name = sheet_name_to_enum_symbol(written_sheet_name) + # enum_symbol = sheet_name_to_enum_symbol(@sheet_name) + # hash_records = CountingBonusVote.valid_records.where(bonus_category: enum_symbol) + + # return unless written_sheet_name.in?(REQUIRED_SHEET_NAMES) + + # hash_records = CountingBonusVote.ranking(@sheet_name) + + # key_to_rank_number = Presenter::Counting.key_to_rank_number_by_sosenkyo_style(hash_records) + # written_data = [] + + # hash_records.each_with_index do |(product_name_and_attack_name, number_of_votes), index| + # row = [] + # product_name = product_name_and_attack_name[0] + # attack_name = product_name_and_attack_name[1] + + # row[@column_name_to_index_hash[:id]] = index + 1 + # row[@column_name_to_index_hash[:順位]] = key_to_rank_number[product_name_and_attack_name] + # row[@column_name_to_index_hash[:作品名]] = product_name + # row[@column_name_to_index_hash[:協力攻撃名]] = attack_name + # row[@column_name_to_index_hash[:全得票数]] = number_of_votes + + # written_data << row + # end + + # delete + + # # TODO: 「ふりがな」を使いたい + # write(written_data.sort_by { |row| [row[1], row[3], row[2]] }) + end + + # def write(written_data) + # SheetData.write_rows( + # sheet_id: ENV.fetch('COUNTING_FINAL_RESULTS_SHEET_ID', nil), + # range: "#{@sheet_name}!A2", # 始点 + # values: written_data + # ) + # end + + # def delete + # SheetData.write_rows( + # sheet_id: ENV.fetch('COUNTING_FINAL_RESULTS_SHEET_ID', nil), + # range: "#{@sheet_name}!A2:E501", + # values: [[''] * 5] * 500 # A列からE列までの 5列 x 500行 を空文字で埋める + # ) + # end + + private + + def this_column_name_to_index_hash + raise + end + + def this_sheet_name + raise + end + + # def column_name_to_index_hash(sheet_name) + # case sheet_name + # when 'ボ・お題小説' + # { + # id: 0, + # キャラ名: 1, + # お題: 2, + # 素得票数: 3, + # 実得票数: 4 + # } + # when 'ボ・推し台詞', 'ボ・開票イラスト', 'ボ・選挙運動' + # { + # id: 0, + # キャラ名: 1, + # 素得票数: 2, + # 実得票数: 3 + # } + # when 'ボ・OP・CLイラスト(オールキャラ)' + # { + # id: 0, + # キャラ名1: 1, + # キャラ名2: 2, + # キャラ名3: 3 + # } + # when 'ボ・OP・CLイラスト(協力攻撃)' + # { + # id: 0, + # 作品名: 1, + # 攻撃名: 2 + # } + # end + # end + + # def sheet_name_to_enum_symbol + # { + # 'ボ・お題小説' => :short_stories, + # 'ボ・推し台詞' => :fav_quotes, + # 'ボ・開票イラスト' => :result_illustrations, + # 'ボ・選挙運動' => :sosenkyo_campaigns, + # 'ボ・OP・CLイラスト(オールキャラ)' => :op_cl_illustrations, + # 'ボ・OP・CLイラスト(協力攻撃)' => :op_cl_illustrations + # }[sheet_name] + # end + end + end + end + end +end diff --git a/app/services/sheets/write_and_update/final_results/bonus_votes/fav_quotes.rb b/app/services/sheets/write_and_update/final_results/bonus_votes/fav_quotes.rb new file mode 100644 index 00000000..98f23c61 --- /dev/null +++ b/app/services/sheets/write_and_update/final_results/bonus_votes/fav_quotes.rb @@ -0,0 +1,63 @@ +module Sheets + module WriteAndUpdate + module FinalResults + module BonusVotes + class FavQuotes < Sheets::WriteAndUpdate::FinalResults::BonusVotes::Base + NUMBER_OF_BONUS_VOTES = 1 + + def exec + records = CountingBonusVote.ranking_fav_quotes + tally_by_character = records.pluck(:character_name).tally + + rows = [] + + tally_by_character.each_with_index do |(character_name, number_of_votes), index| + row = [] + + row[@column_name_to_index_hash[:id]] = index + 1 + row[@column_name_to_index_hash[:キャラ名]] = character_name + row[@column_name_to_index_hash[:投稿数]] = number_of_votes + row[@column_name_to_index_hash[:最終集計得票数]] = NUMBER_OF_BONUS_VOTES + + rows << row + end + + delete + write(rows) + end + + private + + def this_sheet_name + 'ボ・推し台詞' + end + + def write(written_data) + SheetData.write_rows( + sheet_id: ENV.fetch('COUNTING_FINAL_RESULTS_SHEET_ID', nil), + range: "#{@sheet_name}!A2", # 始点 + values: written_data + ) + end + + def delete + SheetData.write_rows( + sheet_id: ENV.fetch('COUNTING_FINAL_RESULTS_SHEET_ID', nil), + range: "#{@sheet_name}!A2:D501", + values: [[''] * 4] * 500 # A列からD列までの列の x 500行 を空文字で埋める + ) + end + + def this_column_name_to_index_hash + { + id: 0, + キャラ名: 1, + 投稿数: 2, + 最終集計得票数: 3 + } + end + end + end + end + end +end diff --git a/app/services/sheets/write_and_update/final_results/bonus_votes/op_cl_illustrations.rb b/app/services/sheets/write_and_update/final_results/bonus_votes/op_cl_illustrations.rb new file mode 100644 index 00000000..0fecf47f --- /dev/null +++ b/app/services/sheets/write_and_update/final_results/bonus_votes/op_cl_illustrations.rb @@ -0,0 +1,63 @@ +module Sheets + module WriteAndUpdate + module FinalResults + module BonusVotes + class OpClIllustrations < Sheets::WriteAndUpdate::FinalResults::BonusVotes::Base + def exec + records = CountingBonusVote.ranking_op_cl_illustrations + + rows = [] + + # オールキャラのみ集計する(協力攻撃は DM 扱いでの集計) + records[:all_characters].each_with_index do |cell_hashes, index| + character_names = cell_hashes.values + + character_names.each do |character_name| + row = [] + + row[@column_name_to_index_hash[:id]] = index + 1 + row[@column_name_to_index_hash[:キャラ名]] = character_name + row[@column_name_to_index_hash[:得票数]] = 1 + + rows << row + end + end + + delete + write(rows) + end + + private + + def this_sheet_name + 'ボ・OP・CLイラスト(オールキャラ)' + end + + def write(written_data) + SheetData.write_rows( + sheet_id: ENV.fetch('COUNTING_FINAL_RESULTS_SHEET_ID', nil), + range: "#{@sheet_name}!A2", # 始点 + values: written_data + ) + end + + def delete + SheetData.write_rows( + sheet_id: ENV.fetch('COUNTING_FINAL_RESULTS_SHEET_ID', nil), + range: "#{@sheet_name}!A2:C501", + values: [[''] * 3] * 500 # A列からC列までの列の x 500行 を空文字で埋める + ) + end + + def this_column_name_to_index_hash + { + id: 0, + キャラ名: 1, + 得票数: 2 + } + end + end + end + end + end +end diff --git a/app/services/sheets/write_and_update/final_results/bonus_votes/result_illustrations.rb b/app/services/sheets/write_and_update/final_results/bonus_votes/result_illustrations.rb new file mode 100644 index 00000000..6bb9294c --- /dev/null +++ b/app/services/sheets/write_and_update/final_results/bonus_votes/result_illustrations.rb @@ -0,0 +1,65 @@ +module Sheets + module WriteAndUpdate + module FinalResults + module BonusVotes + class ResultIllustrations < Sheets::WriteAndUpdate::FinalResults::BonusVotes::Base + NUMBER_OF_BONUS_VOTES = 1 + + def exec + records = CountingBonusVote.ranking_result_illustrations + + rows = [] + + records.each_with_index do |record, index| + row = [] + + character_name = record[:name] + number_of_applications = record[:number_of_applications] + + row[@column_name_to_index_hash[:id]] = index + 1 + row[@column_name_to_index_hash[:キャラ名]] = character_name + row[@column_name_to_index_hash[:投稿数]] = number_of_applications + row[@column_name_to_index_hash[:最終集計得票数]] = NUMBER_OF_BONUS_VOTES + + rows << row + end + + delete + write(rows) + end + + private + + def this_sheet_name + 'ボ・開票イラスト' + end + + def write(written_data) + SheetData.write_rows( + sheet_id: ENV.fetch('COUNTING_FINAL_RESULTS_SHEET_ID', nil), + range: "#{@sheet_name}!A2", # 始点 + values: written_data + ) + end + + def delete + SheetData.write_rows( + sheet_id: ENV.fetch('COUNTING_FINAL_RESULTS_SHEET_ID', nil), + range: "#{@sheet_name}!A2:D501", + values: [[''] * 4] * 500 # A列からD列までの列の x 500行 を空文字で埋める + ) + end + + def this_column_name_to_index_hash + { + id: 0, + キャラ名: 1, + 投稿数: 2, + 最終集計得票数: 3 + } + end + end + end + end + end +end diff --git a/app/services/sheets/write_and_update/final_results/bonus_votes/short_stories.rb b/app/services/sheets/write_and_update/final_results/bonus_votes/short_stories.rb new file mode 100644 index 00000000..cea57944 --- /dev/null +++ b/app/services/sheets/write_and_update/final_results/bonus_votes/short_stories.rb @@ -0,0 +1,63 @@ +module Sheets + module WriteAndUpdate + module FinalResults + module BonusVotes + class ShortStories < Sheets::WriteAndUpdate::FinalResults::BonusVotes::Base + NUMBER_OF_BONUS_VOTES = 1 + + def exec + records = CountingBonusVote.ranking_short_stories + tally_by_character = records.pluck(:character_name).tally + + rows = [] + + tally_by_character.each_with_index do |(character_name, number_of_votes), index| + row = [] + + row[@column_name_to_index_hash[:id]] = index + 1 + row[@column_name_to_index_hash[:キャラ名]] = character_name + row[@column_name_to_index_hash[:投稿数]] = number_of_votes + row[@column_name_to_index_hash[:最終集計得票数]] = NUMBER_OF_BONUS_VOTES + + rows << row + end + + delete + write(rows) + end + + private + + def this_sheet_name + 'ボ・お題小説' + end + + def write(written_data) + SheetData.write_rows( + sheet_id: ENV.fetch('COUNTING_FINAL_RESULTS_SHEET_ID', nil), + range: "#{@sheet_name}!A2", # 始点 + values: written_data + ) + end + + def delete + SheetData.write_rows( + sheet_id: ENV.fetch('COUNTING_FINAL_RESULTS_SHEET_ID', nil), + range: "#{@sheet_name}!A2:D501", + values: [[''] * 4] * 500 # A列からD列までの列の x 500行 を空文字で埋める + ) + end + + def this_column_name_to_index_hash + { + id: 0, + キャラ名: 1, + 投稿数: 2, + 最終集計得票数: 3 + } + end + end + end + end + end +end diff --git a/app/services/sheets/write_and_update/final_results/bonus_votes/sosenkyo_campaigns.rb b/app/services/sheets/write_and_update/final_results/bonus_votes/sosenkyo_campaigns.rb new file mode 100644 index 00000000..57872883 --- /dev/null +++ b/app/services/sheets/write_and_update/final_results/bonus_votes/sosenkyo_campaigns.rb @@ -0,0 +1,63 @@ +module Sheets + module WriteAndUpdate + module FinalResults + module BonusVotes + class SosenkyoCampaigns < Sheets::WriteAndUpdate::FinalResults::BonusVotes::Base + NUMBER_OF_BONUS_VOTES = 2 + + def exec + records = CountingBonusVote.ranking_sosenkyo_campaigns + tally_by_character = records.pluck(:character_name).tally + + rows = [] + + tally_by_character.each_with_index do |(character_name, number_of_votes), index| + row = [] + + row[@column_name_to_index_hash[:id]] = index + 1 + row[@column_name_to_index_hash[:キャラ名]] = character_name + row[@column_name_to_index_hash[:投稿数]] = number_of_votes + row[@column_name_to_index_hash[:最終集計得票数]] = NUMBER_OF_BONUS_VOTES + + rows << row + end + + delete + write(rows) + end + + private + + def this_sheet_name + 'ボ・選挙運動' + end + + def write(written_data) + SheetData.write_rows( + sheet_id: ENV.fetch('COUNTING_FINAL_RESULTS_SHEET_ID', nil), + range: "#{@sheet_name}!A2", # 始点 + values: written_data + ) + end + + def delete + SheetData.write_rows( + sheet_id: ENV.fetch('COUNTING_FINAL_RESULTS_SHEET_ID', nil), + range: "#{@sheet_name}!A2:D501", + values: [[''] * 4] * 500 # A列からD列までの列の x 500行 を空文字で埋める + ) + end + + def this_column_name_to_index_hash + { + id: 0, + キャラ名: 1, + 投稿数: 2, + 最終集計得票数: 3 + } + end + end + end + end + end +end diff --git a/app/services/sheets/write_and_update/final_results/unite_attacks.rb b/app/services/sheets/write_and_update/final_results/unite_attacks.rb index 3537c23f..b6d85386 100644 --- a/app/services/sheets/write_and_update/final_results/unite_attacks.rb +++ b/app/services/sheets/write_and_update/final_results/unite_attacks.rb @@ -10,34 +10,78 @@ def initialize 作品名: 2, 協力攻撃名: 3, 全得票数: 4, - 投票方法内訳・ツイート: 8, - 投票方法内訳・DM: 9 + フリガナ: 5, + ツイートテンプレ: 6 } end def exec - hash_records = CountingUniteAttack.valid_records.full_ranking + hash_records = CountingUniteAttack.valid_records.ranking key_to_rank_number = Presenter::Counting.key_to_rank_number_by_sosenkyo_style(hash_records) written_data = [] - hash_records.each_with_index do |(product_name_and_attack_name, number_of_votes), index| + hash_records.each_with_index do |(product_name_and_attack_name_and_kana, number_of_votes), index| row = [] - product_name = product_name_and_attack_name[0] - attack_name = product_name_and_attack_name[1] + + rank_number = key_to_rank_number[product_name_and_attack_name_and_kana] + product_name = product_name_and_attack_name_and_kana[0] + attack_name = product_name_and_attack_name_and_kana[1] + kana = product_name_and_attack_name_and_kana[2] + tweet_template = tweet_template(rank_number, number_of_votes, product_name, attack_name) row[@column_name_to_index_hash[:id]] = index + 1 - row[@column_name_to_index_hash[:順位]] = key_to_rank_number[product_name_and_attack_name] + row[@column_name_to_index_hash[:順位]] = rank_number row[@column_name_to_index_hash[:作品名]] = product_name row[@column_name_to_index_hash[:協力攻撃名]] = attack_name row[@column_name_to_index_hash[:全得票数]] = number_of_votes + row[@column_name_to_index_hash[:フリガナ]] = kana + row[@column_name_to_index_hash[:ツイートテンプレ]] = tweet_template written_data << row end delete - # TODO: 「ふりがな」を使いたい - write(written_data.sort_by { |row| [row[1], row[3], row[2]] }) + write(written_data.sort_by { |row| [row[1], row[5]] }) + end + + def tweet_template(rank_number, number_of_votes, product_name, attack_name) + rank = rank_number + text_rank_and_votes = "[第#{rank}位] #{number_of_votes}票" + text_hashtags = "#幻水総選挙開票中\n#幻水総選挙2022" + + product_name_to_sheet_name = { + '幻想水滸伝' => '幻水I', + '幻想水滸伝II' => '幻水II', + '幻想水滸伝III' => '幻水III', + '幻想水滸伝IV' => '幻水IV', + 'ラプソディア' => 'Rhapsodia', + '幻想水滸伝V' => '幻水V', + '幻想水滸伝ティアクライス' => 'TK', + '幻想水滸伝 紡がれし百年の時' => '紡時' + } + + origin_record = OnRawSheetUniteAttack.find_by( + sheet_name: product_name_to_sheet_name[product_name], + name: attack_name + ) + + character_names = Presenter::UniteAttacks.character_names(origin_record) + annotation = origin_record.page_annotation.present? ? "※#{origin_record.page_annotation}\n" : '' + + inserted_hash = {} + inserted_hash[:rank] = rank + inserted_hash[:text] = <<~TWEET + #{text_rank_and_votes} + #{product_name} + #{attack_name} + (#{character_names}) + #{annotation} + #{text_hashtags} + TWEET + inserted_hash[:text].chomp! + + inserted_hash[:text] end def write(written_data) @@ -51,8 +95,8 @@ def write(written_data) def delete SheetData.write_rows( sheet_id: ENV.fetch('COUNTING_FINAL_RESULTS_SHEET_ID', nil), - range: "#{@sheet_name}!A2:E501", - values: [[''] * 5] * 500 # A列からE列までの 5列 x 500行 を空文字で埋める + range: "#{@sheet_name}!A2:G501", + values: [[''] * 7] * 500 # A列からG列までの列の 500行 を空文字で埋める ) end end diff --git a/app/services/sheets/write_and_update/final_results/united_all_characters.rb b/app/services/sheets/write_and_update/final_results/united_all_characters.rb new file mode 100644 index 00000000..27e75e3f --- /dev/null +++ b/app/services/sheets/write_and_update/final_results/united_all_characters.rb @@ -0,0 +1,365 @@ +module Sheets + module WriteAndUpdate + module FinalResults + class UnitedAllCharacters + def initialize + puts '[LOG] FinalResults::UnitedAllCharacters.initialize 開始' # rubocop:disable Rails/Output + + @sheet_name = '最終・①オールキャラ部門' + @column_name_to_index_hash = { + id: 0, + 順位: 1, + キャラ名: 2, + 全得票数: 3, + # "": 4, + 部門得票数: 5, + ボ・OP・CLイラスト: 6, + ボ・お題小説: 7, + ボ・開票イラスト: 8, + ボ・推し台詞: 9, + ボ・選挙運動: 10, + # "": 11, + 開票イラストがある?: 12, + 推しセリフがある?: 13, + 登場作品名: 14, + キャラDBに存在する?: 15, + ツイートテンプレート: 16 + } + @all_characters_rows = all_characters_rows + @bonus_short_stories_rows = bonus_short_stories_rows + @bonus_fav_quotes_rows = bonus_fav_quotes_rows + @bonus_result_illustrations_rows = bonus_result_illustrations_rows + @bonus_campaigns_rows = bonus_campaigns_rows + @bonus_op_cl_rows = bonus_op_cl_rows + + puts '[LOG] シート別インスタンス変数の生成完了' # rubocop:disable Rails/Output + + @united_rows = [] + + all_character_names = @all_characters_rows.pluck(:character_name).push(@bonus_short_stories_rows.pluck(:character_name)) + .push(@bonus_fav_quotes_rows.pluck(:character_name)).push(@bonus_result_illustrations_rows.pluck(:character_name)) + .push(@bonus_campaigns_rows.pluck(:character_name)).push(@bonus_op_cl_rows.pluck(:character_name)) + all_character_names.flatten!.uniq! + + all_character_names.each do |character_name| + character_in_all_characters_rows = @all_characters_rows.find { |row| row[:character_name] == character_name } + + this_character_number_of_bonus_votes = set_this_character_number_of_bonus_votes(character_name) + this_number_of_division_votes = character_in_all_characters_rows.blank? ? 0 : character_in_all_characters_rows[:number_of_votes] + this_result_illustration_exist = this_character_number_of_bonus_votes[:result_illustrations].positive? + this_fav_quotes_exist = this_character_number_of_bonus_votes[:fav_quotes].positive? + this_product_names = Presenter::Common.formatted_product_names_for_tweet(character_name) + this_exist_in_character_db = Character.exists?(name: character_name) + + @united_rows << { + character_name: character_name, + number_of_division_votes: this_number_of_division_votes, + number_of_bonus_votes: this_character_number_of_bonus_votes, + united_number_of_votes: this_number_of_division_votes + this_character_number_of_bonus_votes.values.sum, + result_illustration_exist: this_result_illustration_exist.to_s.upcase, + fav_quotes_exist: this_fav_quotes_exist.to_s.upcase, + product_names: this_product_names, + exist_in_character_db: this_exist_in_character_db.to_s.upcase + } + end + + @united_rows.sort_by! do |row| + # 票数の降順でソートする + [ + -row[:united_number_of_votes], row[:character_name] + ] + end + + @united_rows = set_rank(@united_rows) + @united_rows = set_exist_same_rank(@united_rows) + + @memoized_tweet_templates = [] + @united_rows = set_tweet_template(@united_rows) + end + + def exec + rows = [] + + @united_rows.each_with_index do |united_row, index| + row = [] + + row[@column_name_to_index_hash[:id]] = index + 1 + row[@column_name_to_index_hash[:順位]] = united_row[:rank] + row[@column_name_to_index_hash[:キャラ名]] = united_row[:character_name] + row[@column_name_to_index_hash[:全得票数]] = united_row[:united_number_of_votes] + row[@column_name_to_index_hash[:部門得票数]] = united_row[:number_of_division_votes] + row[@column_name_to_index_hash[:ボ・OP・CLイラスト]] = united_row.dig(:number_of_bonus_votes, :op_cl) + row[@column_name_to_index_hash[:ボ・お題小説]] = united_row.dig(:number_of_bonus_votes, :short_stories) + row[@column_name_to_index_hash[:ボ・開票イラスト]] = united_row.dig(:number_of_bonus_votes, :result_illustrations) + row[@column_name_to_index_hash[:ボ・推し台詞]] = united_row.dig(:number_of_bonus_votes, :fav_quotes) + row[@column_name_to_index_hash[:ボ・選挙運動]] = united_row.dig(:number_of_bonus_votes, :campaigns) + row[@column_name_to_index_hash[:開票イラストがある?]] = united_row[:result_illustration_exist] + row[@column_name_to_index_hash[:推しセリフがある?]] = united_row[:fav_quotes_exist] + row[@column_name_to_index_hash[:登場作品名]] = united_row[:product_names] + row[@column_name_to_index_hash[:キャラDBに存在する?]] = united_row[:exist_in_character_db] + row[@column_name_to_index_hash[:ツイートテンプレート]] = united_row[:tweet_template] + + rows << row + end + + delete + write(rows) + end + + def write(written_data) + SheetData.write_rows( + sheet_id: final_results_sheet_id, + range: "#{@sheet_name}!A2", # 始点 + values: written_data + ) + end + + def delete + SheetData.write_rows( + sheet_id: final_results_sheet_id, + range: "#{@sheet_name}!A2:Q501", + values: [[''] * 17] * 500 # A列からQ列までの 17列 x 500行 を空文字で埋める + ) + end + + private + + def set_tweet_template(united_rows) + with_tweet_template_united_rows = [] + + united_rows.each do |united_row| + rank = united_row[:rank] + memo = @memoized_tweet_templates.find { |template| template[:rank] == rank } + + if memo.present? + with_tweet_template_united_rows << { + tweet_template: memo[:tweet_template] + }.merge(united_row) + + next + end + + number_of_votes = united_row[:united_number_of_votes] + exist_same_rank = united_row[:exist_same_rank] + + names_on_the_same_rank = united_rows.find_all { |u_row| u_row[:rank] == rank }.pluck(:character_name) + + text_rank_and_votes = "[第#{rank}位] #{number_of_votes}票" + text_exist_same_rank = exist_same_rank ? "※同率順位あり\n" : '' + text_hashtags = "#幻水総選挙開票中\n#幻水総選挙2022" + + text_names_and_products = '' + names_on_the_same_rank.each do |character_name| + product_names_for_tweet = '' + product_names_for_tweet = Presenter::Common.formatted_product_names_for_tweet(character_name) if Character.where(name: character_name).present? + + text_names_and_products += "#{character_name} #{product_names_for_tweet}\n" + end + text_names_and_products.chomp! + + tmp_hash = {} + tmp_hash[:tweet_template] = <<~TWEET + #{text_rank_and_votes} + #{text_names_and_products} + #{text_exist_same_rank} + #{text_hashtags} + TWEET + tmp_hash[:tweet_template].chomp! + + # メモ化 + @memoized_tweet_templates << { + rank: rank, + tweet_template: tmp_hash[:tweet_template] + } + + with_tweet_template_united_rows << tmp_hash.merge(united_row) + end + + with_tweet_template_united_rows + end + + def final_results_sheet_id + ENV.fetch('COUNTING_FINAL_RESULTS_SHEET_ID', nil) + end + + # 単体・①オールキャラ部門 + def all_characters_rows + sheet_name = '単体・①オールキャラ部門' + rows = SheetData.get_rows(sheet_id: final_results_sheet_id, range: "#{sheet_name}!B2:L501") + all_characters_rows = [] + + rows.each do |row| + all_characters_rows << { + rank: row[0], + character_name: row[1], + number_of_votes: row[2].to_i, + result_illustration_exist: row[4], + fav_quotes_exist: row[5], + product_names: row[6], + exist_in_character_db: row[7], + tweet_template: row[9] + } + end + + all_characters_rows + end + + # ボ・お題小説 + def bonus_short_stories_rows + sheet_name = 'ボ・お題小説' + rows = SheetData.get_rows(sheet_id: final_results_sheet_id, range: "#{sheet_name}!B2:L501") + bonus_short_stories_rows = [] + + rows.each do |row| + bonus_short_stories_rows << { + character_name: row[0], + number_of_votes: row[2].to_i + } + end + + bonus_short_stories_rows + end + + # ボ・推し台詞 + def bonus_fav_quotes_rows + sheet_name = 'ボ・推し台詞' + rows = SheetData.get_rows(sheet_id: final_results_sheet_id, range: "#{sheet_name}!B2:L501") + bonus_fav_quotes_rows = [] + + rows.each do |row| + bonus_fav_quotes_rows << { + character_name: row[0], + number_of_votes: row[2].to_i + } + end + + bonus_fav_quotes_rows + end + + # ボ・開票イラスト + def bonus_result_illustrations_rows + sheet_name = 'ボ・開票イラスト' + rows = SheetData.get_rows(sheet_id: final_results_sheet_id, range: "#{sheet_name}!B2:L501") + bonus_result_illustrations_rows = [] + + rows.each do |row| + bonus_result_illustrations_rows << { + character_name: row[0], + number_of_votes: row[2].to_i + } + end + + bonus_result_illustrations_rows + end + + # ボ・選挙運動 + def bonus_campaigns_rows + sheet_name = 'ボ・選挙運動' + rows = SheetData.get_rows(sheet_id: final_results_sheet_id, range: "#{sheet_name}!B2:L501") + bonus_campaigns_rows = [] + + rows.each do |row| + bonus_campaigns_rows << { + character_name: row[0], + number_of_votes: row[2].to_i + } + end + + bonus_campaigns_rows + end + + # ボ・OP・CLイラスト(オールキャラ) + def bonus_op_cl_rows + sheet_name = 'ボ・OP・CLイラスト(オールキャラ)' + rows = SheetData.get_rows(sheet_id: final_results_sheet_id, range: "#{sheet_name}!B2:L501") + bonus_op_cl_rows = [] + + rows.each do |row| + bonus_op_cl_rows << { + character_name: row[0], + number_of_votes: row[1].to_i + } + end + + bonus_op_cl_rows + end + + # united_rows は票数の降順でソートされているものとする + def set_rank(united_rows) + current_rank = 1 + with_rank_united_rows = [] + + united_rows.each_with_index do |united_row, index| + tmp_hash = {} + + if index == 0 + tmp_hash[:rank] = current_rank + else + previous_number_of_votes = united_rows[index - 1][:united_number_of_votes] + + if united_row[:united_number_of_votes] == previous_number_of_votes + tmp_hash[:rank] = current_rank + else + tmp_hash[:rank] = current_rank + 1 + + current_rank += 1 + end + end + + with_rank_united_rows << tmp_hash.merge(united_row) + end + + with_rank_united_rows + end + + # set_rank 済みの united_rows が引数となる(すさまじい密結合) + def set_exist_same_rank(united_rows) + with_exist_same_rank_united_rows = [] + + united_rows.each_with_index do |united_row, index| + tmp_hash = {} + + tmp_hash[:exist_same_rank] = case index + when 0 + united_row[:rank] == united_rows[1][:rank] + when united_rows.size - 1 + united_row[:rank] == united_rows[index - 1][:rank] + else + united_row[:rank] == united_rows[index - 1][:rank] || united_row[:rank] == united_rows[index + 1][:rank] + end + + with_exist_same_rank_united_rows << tmp_hash.merge(united_row) + end + + with_exist_same_rank_united_rows + end + + def set_this_character_number_of_bonus_votes(character_name) + this_character_number_of_bonus_votes = {} + + this_character_number_of_bonus_votes[:short_stories] = @bonus_short_stories_rows.find do |bonus_short_story_row| + bonus_short_story_row[:character_name] == character_name + end.try(:[], :number_of_votes) || 0 + + this_character_number_of_bonus_votes[:fav_quotes] = @bonus_fav_quotes_rows.find do |bonus_fav_quote_row| + bonus_fav_quote_row[:character_name] == character_name + end.try(:[], :number_of_votes) || 0 + + this_character_number_of_bonus_votes[:result_illustrations] = @bonus_result_illustrations_rows.find do |bonus_result_illustration_row| + bonus_result_illustration_row[:character_name] == character_name + end.try(:[], :number_of_votes) || 0 + + this_character_number_of_bonus_votes[:campaigns] = @bonus_campaigns_rows.find do |bonus_campaign_row| + bonus_campaign_row[:character_name] == character_name + end.try(:[], :number_of_votes) || 0 + + this_character_number_of_bonus_votes[:op_cl] = @bonus_op_cl_rows.find do |bonus_op_cl_row| + bonus_op_cl_row[:character_name] == character_name + end.try(:[], :number_of_votes) || 0 + + this_character_number_of_bonus_votes + end + end + end + end +end diff --git a/app/services/sheets/write_and_update/final_summary/fav_quotes.rb b/app/services/sheets/write_and_update/final_summary/fav_quotes.rb new file mode 100644 index 00000000..6e0502f6 --- /dev/null +++ b/app/services/sheets/write_and_update/final_summary/fav_quotes.rb @@ -0,0 +1,77 @@ +module Sheets + module WriteAndUpdate + module FinalSummary + class FavQuotes + def initialize + @sheet_name = 'まとめ' + @column_name_to_index_hash = { + id: 0, + シートid: 1, + 投稿方法: 2, + 投稿内容: 3, + キャラ名: 4, + 台詞のみ(カギカッコ不要): 5, # シート側で入力 + 備考: 6, # シート側で入力 + 第一候補: 7, # シート側で入力 + 第二候補: 8, # シート側で入力 + 文字数: 9 # シート側で入力 + } + end + + def exec + base_records = CountingBonusVote.valid_records.where(bonus_category: :fav_quotes) + chara_columns = %i[chara_01 chara_02 chara_03 chara_04 chara_05 chara_06 chara_07 chara_08 chara_09 chara_10] + + rows = [] + + base_records.each_with_index do |record, index| + character_names = chara_columns.map { |c| record[c] }.compact_blank.reject { |el| el == "FALSE"} + + # キャラが複数いる場合には分割する(一キャラ一台詞一レコード) + character_names.each do |character_name| + row = [] + + id = index + 1 + sheet_id = record.id_on_sheet + vote_method = record.vote_method + contents = record.contents + + row[@column_name_to_index_hash[:id]] = id + row[@column_name_to_index_hash[:シートid]] = sheet_id + row[@column_name_to_index_hash[:投稿方法]] = vote_method + row[@column_name_to_index_hash[:投稿内容]] = contents + row[@column_name_to_index_hash[:キャラ名]] = character_name + + rows << row + end + end + + rows = rows.sort_by do |element_array| + [ + element_array[@column_name_to_index_hash[:キャラ名]], + ] + end + + delete + write(rows) + end + + def write(written_data) + SheetData.write_rows( + sheet_id: ENV.fetch('FINAL_SUMMARY_FAV_QUOTES_SHEET_ID', nil), + range: "#{@sheet_name}!A2", # 始点 + values: written_data + ) + end + + def delete + SheetData.write_rows( + sheet_id: ENV.fetch('FINAL_SUMMARY_FAV_QUOTES_SHEET_ID', nil), + range: "#{@sheet_name}!A2:E501", + values: [[''] * 5] * 500 # A列からE列までの列 の 500行 を空文字で埋める + ) + end + end + end + end +end diff --git a/app/services/sheets/write_and_update/final_summary/short_stories.rb b/app/services/sheets/write_and_update/final_summary/short_stories.rb new file mode 100644 index 00000000..c5aa1b7a --- /dev/null +++ b/app/services/sheets/write_and_update/final_summary/short_stories.rb @@ -0,0 +1,67 @@ +module Sheets + module WriteAndUpdate + module FinalSummary + class ShortStories + def initialize + @sheet_name = 'まとめ' + @column_name_to_index_hash = { + id: 0, + id_on_sheet: 1, + 投稿方法: 2, + URL: 3, + 「お題」: 4, + 内容: 5, + 開票後の紹介可: 6, # 手動入力 + キャラ名: 7 + } + end + + def exec + base_records = CountingBonusVote.ranking_short_stories + rows = [] + + base_records.each_with_index do |record, index| + row = [] + + row[@column_name_to_index_hash[:id]] = index + 1 + row[@column_name_to_index_hash[:id_on_sheet]] = record[:id_on_sheet] + row[@column_name_to_index_hash[:投稿方法]] = record[:vote_method] + row[@column_name_to_index_hash[:URL]] = record[:url] + row[@column_name_to_index_hash[:「お題」]] = record[:theme] + row[@column_name_to_index_hash[:内容]] = record[:contents] + row[@column_name_to_index_hash[:キャラ名]] = record[:character_name] + + rows << row + end + + rows = rows.sort_by do |element_array| + [ + element_array[@column_name_to_index_hash[:キャラ名]], + ] + end + + delete + write(rows) + end + + def write(written_data) + SheetData.write_rows( + sheet_id: ENV.fetch('FINAL_SUMMARY_SHORT_STORIES_SHEET_ID', nil), + range: "#{@sheet_name}!A2", # 始点 + values: written_data + ) + end + + def delete + SheetData.write_rows( + sheet_id: ENV.fetch('FINAL_SUMMARY_SHORT_STORIES_SHEET_ID', nil), + range: "#{@sheet_name}!A2:H501", + values: [ + ['', '', '', '', '', '', nil, ''], + ] * 500 + ) + end + end + end + end +end diff --git a/clasp/package.json b/clasp/package.json index 6e99683e..9b6aa4a8 100644 --- a/clasp/package.json +++ b/clasp/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "devDependencies": { "@google/clasp": "2.4.1", - "@types/google-apps-script": "1.0.50" + "@types/google-apps-script": "1.0.51" }, "license": "MIT", "main": "index.js" diff --git a/clasp/yarn.lock b/clasp/yarn.lock index 9e7578e1..88bed9c4 100644 --- a/clasp/yarn.lock +++ b/clasp/yarn.lock @@ -81,10 +81,10 @@ "@types/node" "*" "@types/responselike" "*" -"@types/google-apps-script@1.0.50": - version "1.0.50" - resolved "https://registry.yarnpkg.com/@types/google-apps-script/-/google-apps-script-1.0.50.tgz#0a77295aae089c1378191cb3fc9bed361b4cdaf5" - integrity sha512-OZQN2ZPvFG25U5KUGUuHF+YpgJhvMz4dnLlm1LzPOy4Z7kcNMW8Nm4KfzpAFqieFId4DGLpA4SPZXPyEtMwPyg== +"@types/google-apps-script@1.0.51": + version "1.0.51" + resolved "https://registry.yarnpkg.com/@types/google-apps-script/-/google-apps-script-1.0.51.tgz#bbaaedf688951c644cd18f6f3a1a08d539ee1c4c" + integrity sha512-v4wg/PasZptA0Lt3TyZMlftA5cc7vP02ytDuuNghh5MCJNDIaYTjokbagi3uCvNKKmSZASjKjfrUQdpER9hACA== "@types/http-cache-semantics@*": version "4.0.1" diff --git a/db/migrate/20220709075058_add_kana_column_to_counting_unite_attack.rb b/db/migrate/20220709075058_add_kana_column_to_counting_unite_attack.rb new file mode 100644 index 00000000..2ebc6132 --- /dev/null +++ b/db/migrate/20220709075058_add_kana_column_to_counting_unite_attack.rb @@ -0,0 +1,5 @@ +class AddKanaColumnToCountingUniteAttack < ActiveRecord::Migration[7.0] + def change + add_column :counting_unite_attacks, :kana, :string + end +end diff --git a/db/migrate/20220711075659_add_chara_columns_to_counting_bonus_vote.rb b/db/migrate/20220711075659_add_chara_columns_to_counting_bonus_vote.rb new file mode 100644 index 00000000..5989e1f2 --- /dev/null +++ b/db/migrate/20220711075659_add_chara_columns_to_counting_bonus_vote.rb @@ -0,0 +1,6 @@ +class AddCharaColumnsToCountingBonusVote < ActiveRecord::Migration[7.0] + def change + add_column :counting_bonus_votes, :chara_11, :string + add_column :counting_bonus_votes, :chara_12, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 5cad100e..2fbd5986 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2022_07_03_105847) do +ActiveRecord::Schema[7.0].define(version: 2022_07_11_075659) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -105,6 +105,8 @@ t.string "chara_10" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "chara_11" + t.string "chara_12" end create_table "counting_unite_attacks", force: :cascade do |t| @@ -122,6 +124,7 @@ t.string "unite_attack_name" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "kana" end create_table "direct_messages", force: :cascade do |t| diff --git a/import_all_counting_data_to_local_db.sh b/import_all_counting_data_to_local_db.sh index f48d9d3d..028f27d8 100755 --- a/import_all_counting_data_to_local_db.sh +++ b/import_all_counting_data_to_local_db.sh @@ -1,11 +1,15 @@ #!/bin/bash -xe -bin/rails runner "CountingAllCharacter.destroy_all" -bin/rails runner "CountingUniteAttack.destroy_all" -bin/rails runner "CountingBonusVote.destroy_all" - +bin/rails runner 'CountingAllCharacter.destroy_all' bin/rails import_counting_all_characters:exec_all -bin/rails import_counting_unite_attacks:exec_all + +# bin/rails runner 'CountingUniteAttack.destroy_all' +# bin/rails import_counting_unite_attacks:exec_all + +bin/rails runner 'CountingBonusVote.destroy_all' bin/rails import_counting_bonus_votes:exec_all +# 開票イラストデータは独立しているのでここでインポートする +bin/rails runner 'puts Sheets::ResultIllustrationApplications.import_totallings_data_to_database' + exit 0 diff --git a/lib/tasks/final_ranking.rake b/lib/tasks/final_ranking.rake new file mode 100644 index 00000000..4a690d1a --- /dev/null +++ b/lib/tasks/final_ranking.rake @@ -0,0 +1,15 @@ +namespace :final_ranking do + desc '「単体・①オールキャラ部門」の最終結果をスプレッドシートに書き込む' + task all_characters_stand_alone: :environment do + o = Sheets::WriteAndUpdate::FinalResults::AllCharactersStandAlone.new + + o.exec + end + + desc '「②協力攻撃部門」の最終結果をスプレッドシートに書き込む' + task unite_attacks: :environment do + o = Sheets::WriteAndUpdate::FinalResults::UniteAttacks.new + + o.exec + end +end diff --git a/lib/tasks/update_kana_column_on_counting_all_atacks.rake b/lib/tasks/update_kana_column_on_counting_all_atacks.rake new file mode 100644 index 00000000..04ba4c4b --- /dev/null +++ b/lib/tasks/update_kana_column_on_counting_all_atacks.rake @@ -0,0 +1,31 @@ +namespace :update_kana_column_on_counting_all_atacks do + desc 'ソート用カラムを CountingUniteAttack の各レコードに追加する' + task exec: :environment do + product_name_to_sheet_name = { + '幻想水滸伝' => '幻水I', + '幻想水滸伝II' => '幻水II', + '幻想水滸伝III' => '幻水III', + '幻想水滸伝IV' => '幻水IV', + 'ラプソディア' => 'Rhapsodia', + '幻想水滸伝V' => '幻水V', + '幻想水滸伝ティアクライス' => 'TK', + '幻想水滸伝 紡がれし百年の時' => '紡時' + } + + ActiveRecord::Base.transaction do + CountingUniteAttack.all.each do |record| + next if record.is_invisible || record.is_out_of_counting || record.product_name.blank? || record.unite_attack_name.blank? + + origin_records = OnRawSheetUniteAttack.where( + sheet_name: product_name_to_sheet_name[record.product_name], + name: record.unite_attack_name + ) + + raise if origin_records.size != 1 + + kana = origin_records.first.kana + record.update!(kana: kana) if record.kana != kana + end + end + end +end diff --git a/write_all_final_result_to_sheets.sh b/write_all_final_result_to_sheets.sh index e95ecc18..8a99431e 100755 --- a/write_all_final_result_to_sheets.sh +++ b/write_all_final_result_to_sheets.sh @@ -1,7 +1,25 @@ #!/bin/bash -xe -bin/rails runner "Sheets::WriteAndUpdate::FinalResults::AllCharactersStandAlone.new.exec" -bin/rails runner "Sheets::WriteAndUpdate::FinalResults::UniteAttacks.new.exec" -# TODO: ボーナス票 +# 単体・①オールキャラ部門 +bin/rails runner 'Sheets::WriteAndUpdate::FinalResults::AllCharactersStandAlone.new.exec' +# bin/rails runner 'Sheets::WriteAndUpdate::FinalResults::UniteAttacks.new.exec' + +# ボ・お題小説 +bin/rails runner 'Sheets::WriteAndUpdate::FinalResults::BonusVotes::ShortStories.new.exec' + +# ボ・開票イラスト +bin/rails runner 'Sheets::WriteAndUpdate::FinalResults::BonusVotes::ResultIllustrations.new.exec' + +# ボ・推し台詞 +bin/rails runner 'Sheets::WriteAndUpdate::FinalResults::BonusVotes::FavQuotes.new.exec' + +# ボ・選挙運動 +bin/rails runner 'Sheets::WriteAndUpdate::FinalResults::BonusVotes::SosenkyoCampaigns.new.exec' + +# ボ・OP・CLイラスト(オールキャラ) +bin/rails runner 'Sheets::WriteAndUpdate::FinalResults::BonusVotes::OpClIllustrations.new.exec' + +# 最終・①オールキャラ部門 +bin/rails runner 'Sheets::WriteAndUpdate::FinalResults::AllCharactersUnited.new.exec' exit 0