class GameController < ApplicationController include QuizHelperMethods skip_before_action :require_player!, only: [ :index, :start ] before_action :set_node, only: [ :stage, :answer, :stage_result ] helper_method :root_node, :stage_index, :n_stages, :last_save_node def index @node = root_node not_found and return unless @node render action: @node.template end # POST def start player = Player.create(locale: I18n.locale.to_s) session[:player_id] = player.id redirect_to action: "facts" end def facts @node = root_node&.children&.facts&.first end def intro @node = root_node&.children&.intro&.first end def stage end # POST def answer @answer = @node.children.find_by(id: params[:value]) @answer = @answer.children.sample if @answer&.chance? current_player.record_answer(stage_index, @answer.id) apply_score(score_entry_for(stage_index, @answer)) bad_chance_outcome = @answer.parent&.chance? && @answer.bad_answer? if stage_index >= n_stages && !bad_chance_outcome redirect_to action: :done else redirect_to action: :stage_result, id: params[:id] end end def stage_result @result_node = @node.descendants.find_by(id: current_player.answer_id_for(stage_index)) not_found and return unless @result_node end def last_save @node = last_save_node end # POST def answer_last_save @node = last_save_node not_found and return unless @node @answer = @node.children.find_by(id: params[:value]) current_player.record_last_save_answer(@answer.id) apply_score(last_save_score_entry_for(@answer)) redirect_to action: :done end def done current_player.update(is_done: true) unless current_player.is_done? if current_player.last_save_answer_id @node = last_save_node @result_node = @node.descendants.find_by(id: current_player.last_save_answer_id) else @node = stages.last @result_node = @node.descendants.find_by(id: current_player.answer_id_for(stages.size)) end end def results @node = root_node.children.results.first end private def root_node @root_node ||= Node.roots.viewable.first end def last_save_node @last_save_node ||= root_node.children.last_save.first end def stages @stages ||= root_node.children.ordered.stage end def set_node @node = stages[params[:id].to_i - 1] not_found and return unless @node end def stage_index @stage_index ||= stages.index(@node) + 1 end def n_stages @n_stages ||= stages.size end def url_from_param return "" unless params[:url] # return File.join('', params[:url]) if I18n.default_locale == I18n.locale File.join("", I18n.locale.to_s, params[:url]) end def question_scores @@question_scores ||= JSON.parse(Rails.root.join("config", "question_scores.json").read) end def score_entry_for(stage_idx, answer_node) stage_data = question_scores["stages"][stage_idx - 1] return nil unless stage_data if answer_node.parent&.chance? chance_entry = stage_data["answers"][answer_node.parent.position - 1] chance_entry&.dig("outcomes", answer_node.position - 1) else stage_data["answers"][answer_node.position - 1] end end def last_save_score_entry_for(answer_node) question_scores.dig("last_save", "answers", answer_node.position - 1) end def apply_score(entry) return unless entry current_player.add_to_score( overall: entry["overall"].to_i, impact: entry["impact"] || {} ) end end