from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants from otree.models_concrete import CompletedGroupWaitPage from django.http import HttpResponseRedirect from random import choice from time import time class FirstWaitPage(WaitPage): group_by_arrival_time = True template_name = 'coordination/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 self.round_number == 1 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 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, 'coordinate', 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 TaskCrdInstructions(Page): template_name = 'coordination/Instructions.html' timeout_seconds = 60 * 2 def is_displayed(self): # Erase start_waiting_for_partners self.participant.vars.pop('start_waiting_for_partners', None) return self.round_number == 1 def vars_for_template(self): partner_treatment = self.player.coordinate_partner if partner_treatment == 'name': partner_name = self.player.get_others_in_group()[0].participant.vars['data']['first_name'] self.player.coordinate_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_house': 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 = '' return {'partner': partner} class TaskCrdDecision(Page): template_name = 'coordination/Decision.html' timeout_seconds = 60 form_model = 'player' form_fields = ['coordinate_decision'] def before_next_page(self): if self.timeout_happened: self.player.coordinate_decision = choice(['A', 'B']) self.player.timeout = True class ResultsWaitPage(WaitPage): def after_all_players_arrive(self): for p in self.group.get_players(): p.set_payoff() class TaskCrdResults(Page): template_name = 'coordination/Results.html' timeout_seconds = Constants.seconds_for_summary def vars_for_template(self): if self.participant.vars.get('other_coordinate'): other_coordinate = self.participant.vars['other_coordinate'] else: other_coordinate = self.player.other_player().coordinate_decision payoff_matrix = dict( A=dict( A=Constants.payoff_action_a, B=Constants.payoff_action_a ), B=dict( A=0, B=Constants.payoff_action_b ) ) if self.player.coordinate_decision: other_payoff = payoff_matrix[other_coordinate][self.player.coordinate_decision] else: other_payoff = payoff_matrix[other_coordinate][choice(['A', 'B'])] return { 'other_coordinate': other_coordinate, 'other_payoff': other_payoff, 'next_round': self.round_number + 1 } def before_next_page(self): if self.round_number == Constants.num_rounds: self.participant.vars['unmatched'] = False page_sequence = [ FirstWaitPage, TaskCrdInstructions, TaskCrdDecision, ResultsWaitPage, TaskCrdResults ]