from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants from statistics import mode import random class GroupingWaitPage(WaitPage): group_by_arrival_time = True title_text = "Team Construction" body_text = "Waiting for more participants to form a team..." def get_players_for_group(self, waiting_players): print('Structuring Teams...') # Collect participants based on their identified roles and shuffle policy_experts = [p for p in waiting_players if p.participant.vars['role'] == 1] cyber_experts = [p for p in waiting_players if p.participant.vars['role'] == 2] military_experts = [p for p in waiting_players if p.participant.vars['role'] == 3] if len(policy_experts) >= 1 and len(cyber_experts) >= 1 and len(military_experts) >= 1: print('Grouping...') return [policy_experts[0], cyber_experts[0], military_experts[0]] print('Not enough players') def is_displayed(self): return self.round_number == 1 class Groupings(Page): def vars_for_template(self): # Get participants per role and extract their names policy_expert = self.group.get_player_by_role("policy").participant.vars['name'] cyber_expert = self.group.get_player_by_role("cyber").participant.vars['name'] military_expert = self.group.get_player_by_role("military").participant.vars['name'] return { 'policy_expert': policy_expert, 'cyber_expert': cyber_expert, 'military_expert': military_expert } def before_next_page(self): rapid = next(Constants.rapid) self.group.rapid = rapid def is_displayed(self): return self.round_number == 1 class Break(Page): timeout_seconds = 30 timer_text = "Time left for break: " def is_displayed(self): return self.round_number < 3 class Role(Page): def vars_for_template(self): return { 'role': self.player.role() } def is_displayed(self): return self.round_number == 1 class ScenarioWaitPage(WaitPage): title_text = "Loading Scenario" body_text = "Waiting for the rest of your group..." def is_displayed(self): return self.round_number == 1 class Scenario(Page): timeout_seconds = 90 timer_text = "Time left to complete this scenario: " form_model = 'player' form_fields = ['choice'] def vars_for_template(self): if self.round_number == 1: options = Constants.options_1.copy() elif self.round_number == 2: options = Constants.options_2.copy() else: options = Constants.options_3.copy() random.shuffle(options) if self.round_number > 1: prev_decision = self.group.in_round(self.round_number - 1).decision rapid = self.group.in_round(self.round_number - 1).rapid # Possible escalation on the second round if self.round_number == 2: return { 'prev_decision': prev_decision, 'round': self.round_number, 'rapid': rapid, 'role': self.player.role(), 'options': options } else: prev_decision = -1 return { 'prev_decision': prev_decision, 'round': self.round_number, 'role': self.player.role(), 'options': options } def before_next_page(self): if self.timeout_happened and self.round_number == 1: self.player.choice = random.randint(1, 4) elif self.timeout_happened and self.round_number == 2: self.player.choice = random.randint(1, 5) elif self.timeout_happened and self.round_number == 3: self.player.choice = random.randint(1, 2) else: pass class ResponseWaitPage(WaitPage): title_text = "Round Transition" body_text = "Waiting for the rest of your group..." def after_all_players_arrive(self): responses = [] dissent = False # Compute result of decision for player in self.group.get_players(): responses.append(player.choice) key = responses[0] for x in responses: if x != key: dissent = True break self.group.dissent = dissent try: decision = mode(responses) self.group.chaos = False except: decision = random.choice(responses) self.group.chaos = True self.group.decision = decision class Conclusion(Page): # Return decision for all previous rounds def vars_for_template(self): return { 'decision_1': self.group.in_round(1).decision, 'decision_2': self.group.in_round(2).decision, 'decision_3': self.group.in_round(3).decision } # Only display when on the last round. def is_displayed(self): return self.round_number == 3 page_sequence = [ GroupingWaitPage, Groupings, Role, ScenarioWaitPage, Scenario, ResponseWaitPage, Break, Conclusion ]