You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

122 lines
3.7 KiB

# Development-only shortcut so any screen can be opened directly instead of
# playing the game from the start. Creates a player on demand and back-fills
# whatever progress the requested screen expects to find.
#
# ?dev=good|bad|chance|chance_bad picks which answer the back-fill records and
# always starts from a fresh player, so the whole run leading up to the screen
# is answered that way. Without it an existing session player is kept and only
# the gaps are filled, so a jump can be played on from. ?dev_last_save=1 also
# answers the last-save question.
module DevJump
extend ActiveSupport::Concern
SCREENS = %w[index facts intro stage stage_result last_save done results].freeze
included do
prepend_before_action :dev_jump!, only: SCREENS.map(&:to_sym), if: :dev_jump?
end
private
def dev_jump?
Rails.env.development?
end
def dev_jump!
set_locale
# The start screen is the one place a leftover player is in the way: it
# would show the debug panel a first-time visitor never sees.
return session.delete(:player_id) if action_name == "index"
session.delete(:player_id) if params[:dev]
dev_player
dev_seed_progress
end
def dev_player
Current.player = Player.find_by(id: session[:player_id])
return Current.player if Current.player
Current.player = Player.create(locale: I18n.locale.to_s,
country: Player.valid_country_code(params[:country]),
device: Player.device_from_user_agent(request.user_agent))
session[:player_id] = Current.player.id
Current.player
end
def dev_seed_progress
case action_name
when "stage" then dev_fill_stages(params[:id].to_i - 1)
when "stage_result" then dev_fill_stages(params[:id].to_i)
when "last_save" then dev_fill_stages(n_stages)
when "done", "results"
dev_fill_stages(n_stages)
dev_fill_last_save if params[:dev_last_save]
end
end
# Answers every stage up to `upto` that the player hasn't answered yet, scoring
# each one the way the real answer action would.
def dev_fill_stages(upto)
return if upto < 1
stages.first(upto).each_with_index do |stage_node, i|
index = i + 1
next if current_player.answer_id_for(index)
answer = dev_answer_for(stage_node)
next unless answer
current_player.record_answer(index, answer.id)
apply_score(score_entry_for(index, answer))
end
end
def dev_fill_last_save
return if current_player.last_save_answer_id
node = last_save_node
return unless node
answer = dev_pick_from(node.children.ordered)
return unless answer
current_player.record_last_save_answer(answer.id)
apply_score(last_save_score_entry_for(answer))
end
# A chance answer is only ever recorded through one of its outcomes, so it
# resolves one level deeper -- ?dev=chance lands on the good outcome,
# ?dev=chance_bad on the bad one.
def dev_answer_for(stage_node)
answer = dev_pick_from(stage_node.children.ordered)
return answer unless answer&.chance?
outcomes = answer.children.ordered.to_a
wanted = params[:dev] == "chance_bad" ? :bad_answer? : :good_answer?
outcomes.find(&wanted) || outcomes.first
end
# Not every stage offers every kind -- stage 5 has no bad answer, stage 1's
# chance cannot go wrong -- so an unavailable pick settles for the first
# answer rather than leaving the stage unanswered.
def dev_pick_from(nodes)
nodes = nodes.to_a
case params[:dev]
when "bad" then nodes.find(&:bad_answer?)
when "chance", "chance_bad" then nodes.find(&:chance?)
else nodes.find(&:good_answer?)
end || nodes.first
end
end