from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants from time import time class FirstWaitPage(WaitPage): group_by_arrival_time = True template_name = 'compete/FirstWaitingPage.html' def is_displayed(self): # After max waiting time has expired mark player as unmatched self.participant.vars.setdefault('start_waiting_for_partners', time()) if self.request: if self.request.method == 'POST': self.participant.vars['unmatched'] = True return True def get_players_for_group(self, waiting_players): for p in waiting_players: p.refresh_from_db() # Move forward unmatched players unmatched = [p for p in waiting_players if p.participant.vars.get('unmatched')] if unmatched: for p in unmatched: p.compete_partner = 'ctrl' if len(unmatched) == 1: return unmatched[:1] elif unmatched: return unmatched[:2] # Group players still waiting for partner(s) still_waiting = [p for p in waiting_players if not p.participant.vars.get('unmatched')] if len(still_waiting) >= 2: return self.subsession.set_partner_based_on_identity(still_waiting, 'compete', 2) def after_all_players_arrive(self): players = self.group.get_players() # Handle potential race condition causing 'unmatched' players to actually be grouped if len(players) > 1: for p in players: if p.participant.vars.get('unmatched'): p.participant.vars.pop('unmatched', None) class TaskSlidersInstructions(Page): template_name = 'compete/Instructions.html' timeout_seconds = 60 * 4 def vars_for_template(self): partner_treatment = self.player.compete_partner if partner_treatment == 'name': partner_name = self.player.get_others_in_group()[0].participant.vars['data']['first_name'] self.player.compete_partner_name = partner_name partner = f"The second participant is called {partner_name}." elif partner_treatment == 'same_class': partner = "The second participant is also in your house." elif partner_treatment == 'other_school': partner = "The second participant is from another house." elif partner_treatment == 'other_region': partner = "The second participant comes from another house/section in the Civil Service Academy." else: partner = '' if self.participant.vars.get('is_teacher'): partner = '' touch = False if self.participant.vars.setdefault('is_mobile', self.request.user_agent.is_mobile) or \ self.participant.vars.setdefault('is_tablet', self.request.user_agent.is_tablet): touch = True return { 'partner': partner, 'touch': touch } form_model = 'player' form_fields = ['compete_decision'] def is_displayed(self): # Erase start_waiting_for_partners self.participant.vars.pop('start_waiting_for_partners', None) return True def before_next_page(self): self.participant.vars['start_task'] = time() if self.timeout_happened: self.player.timeout = True self.player.compete_decision = 0 class TaskSliders(Page): timeout_seconds = Constants.time_for_task * 60 + 5 template_name = 'compete/SliderTaskPage.html' form_model = 'player' form_fields = ['centered_sliders'] def vars_for_template(self): touch = False if self.participant.vars['is_mobile'] or self.participant.vars['is_tablet']: touch = True return {'touch': touch} class WaitingPage(WaitPage): def after_all_players_arrive(self): for p in self.group.get_players(): p.set_payoff() class TaskSlidersResults(Page): template_name = 'compete/Results.html' timeout_seconds = 60 def vars_for_template(self): if self.player.compete_decision: choice = Constants.option_b if self.participant.vars.get('unmatched'): centered_sliders_by_other = self.participant.vars['other_sliders'] else: centered_sliders_by_other = self.player.get_others_in_group()[0].centered_sliders else: choice = Constants.option_a centered_sliders_by_other = None return { 'choice': choice, 'centered_sliders_by_other': centered_sliders_by_other } def before_next_page(self): if self.round_number == Constants.num_rounds: self.participant.vars['unmatched'] = False page_sequence = [ FirstWaitPage, TaskSlidersInstructions, TaskSliders, WaitingPage, TaskSlidersResults ]