from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) import random import itertools from collections import defaultdict import numpy as np from django import forms from django.forms import widgets as django_widgets import math import time author = 'Jindi Huang' doc = """ Game Complexity """ class Constants(BaseConstants): name_in_url = 'game_stage1' players_per_group = 4 round_per_game = 5 num_rounds = 3 + 3*round_per_game signal_interval = 0.25 signal_max = 15 signal_num = int(signal_max/signal_interval) budget = 20 list1 = np.arange(1 * 20, - 1, -1) list2 = [] list2.append(0) for x in range(20): list2.append((x+1)*5) class Subsession(BaseSubsession): def creating_session(self): if self.round_number == 1: for player in self.get_players(): player.participant.vars['game_payment'] = 0 player.participant.vars['total_payment'] = self.session.config['participation_fee'] player.participant.vars['correct_num'] = 4 player.participant.vars['correct_payment'] = 0 player.participant.vars['instruction_round'] = [1, 1 + Constants.round_per_game + 1, 1 + 2*(Constants.round_per_game+1)] player.participant.vars['payround'] = random.choice([i for i in range(1, Constants.num_rounds+1) if i not in player.participant.vars['instruction_round']]) player.participant.vars['payin15'] = random.choice([i for i in range(1, 16)]) player.participant.vars['start_time'] = 0 player.participant.vars['failed_first_comprehension'] = False player.participant.vars['skip'] = False for player in self.get_players(): player.signal = c(Constants.signal_interval * random.randint(0, Constants.signal_num)) player.set_current_play() def group_by_arrival_time_method(self, waiting_players): if len(waiting_players) >= Constants.players_per_group: return waiting_players[:Constants.players_per_group] for p in waiting_players: if p.waiting_too_long(): p.participant.vars['skip'] = True return [p] class Group(BaseGroup): aa_stop = models.IntegerField(initial=0) no_winner = models.IntegerField() bid1 = models.CurrencyField() bid2 = models.CurrencyField() bid3 = models.CurrencyField() bid4 = models.CurrencyField() start = models.IntegerField(initial=0) current_play = models.StringField() def set_payoffs(self): players = self.get_players() bids = [p.bid for p in players if p.bid != None] bids.sort(reverse=True) try: self.bid1 = bids[0] except IndexError: self.bid1 = 0 try: self.bid2 = bids[1] except IndexError: self.bid2 = 0 try: self.bid3 = bids[2] except IndexError: self.bid3 = 0 try: self.bid4 = bids[3] except IndexError: self.bid4 = 0 if self.bid1 == self.bid2: self.no_winner = 1 for player in players: player.round_payoff = c(0) player.winner = 0 else: for player in players: if player.current_play != 'aa': if player.bid == self.bid1: player.winner = 1 if player.current_play == 'fp': player.round_payoff = player.signal - player.bid else: if self.bid2 == None: player.round_payoff = player.signal else: player.round_payoff = player.signal - self.bid2 elif player.bid == None: player.winner = 0 player.round_payoff = c(-1 * self.session.config['baseline_bonus']) else: player.winner = 0 player.round_payoff = c(0) else: if player.bid == None: player.winner = 1 player.round_payoff = player.signal - self.bid1 else: player.winner = 0 player.round_payoff = c(0) for player in players: if player.participant.vars['payin15'] == 15: if self.round_number == player.participant.vars['payround']: player.game_payment = player.round_payoff + self.session.config['baseline_bonus'] player.participant.vars['game_payment'] = c(player.game_payment) player.total_payment = player.game_payment + self.session.config['participation_fee'] player.participant.vars['total_payment'] = c(player.total_payment) else: player.total_payment = self.session.config['participation_fee'] player.participant.vars['total_payment'] = c(player.total_payment) class Player(BasePlayer): bid = models.CurrencyField(label=False, blank=True) signal = models.CurrencyField() current_play = models.StringField() current_game = models.IntegerField() current_round = models.IntegerField() round_payoff = models.CurrencyField() winner = models.IntegerField() total_payment = models.CurrencyField() game_payment = models.CurrencyField() group_size = models.IntegerField(initial=Constants.players_per_group) prolific_id = models.StringField() stop_help = models.IntegerField(blank=True) skip = models.BooleanField(initial=False) def set_current_play(self): if self.round_number <= Constants.num_rounds / 3: self.current_play = 'fp' self.current_game = 1 if self.round_number > Constants.num_rounds/3 and self.round_number <= 2*Constants.num_rounds/3: self.current_play = 'sp' self.current_game = 2 if self.round_number > 2*Constants.num_rounds/3: self.current_play = 'aa' self.current_game = 3 if self.session.config['category'] == 'aa' and self.round_number <= Constants.num_rounds / 3: self.current_play = 'aa' self.current_game = 1 if self.session.config['category'] == 'aa' and self.round_number > Constants.num_rounds / 3 and self.round_number <= 2 * Constants.num_rounds / 3: self.current_play = 'sp' self.current_game = 2 if self.session.config['category'] == 'aa' and self.round_number > 2 * Constants.num_rounds / 3: self.current_play = 'fp' self.current_game = 3 self.current_round = self.round_number - self.current_game - Constants.round_per_game * (self.current_game - 1) def live_aa(self, bid): t = bid['type'] if t == "time": self.group.start += 1 if self.group.start == Constants.players_per_group: self.participant.vars['start_time'] = bid['value'] if self.group.start >= Constants.players_per_group: response = dict(start=1, start_time=self.participant.vars['start_time'], stop=0) else: response = dict(start=0, start_time=self.participant.vars['start_time'], stop=0) return {0: response} if t == "stop": self.group.aa_stop += 1 if self.group.aa_stop >= Constants.players_per_group - 1: response = dict(start=0, start_time=0, stop=1) return {0: response} def bid_error_message(self, value): possible = [999] i = 0 while i <= 20: possible.append(i) i = i + 0.25 if value is not None: if value not in possible: return "All bids must be between $0 and $20 and in 25 cent increments." qn_win = models.IntegerField( choices=[ [1, 'Alice'], [2, 'Bob'], [3, 'Clair'], [4, 'David'], ], widget=widgets.RadioSelect, blank=False, label="" ) qn_pay = models.IntegerField( choices=[ [1, '$20'], [2, '$21'], [3, '$23'], [4, '$24'], ], widget=widgets.RadioSelect, blank=False, label="" ) qn_win_got_wrong = models.BooleanField(initial=False) qn_pay_got_wrong = models.BooleanField(initial=False) failed_comprehension_auction = models.BooleanField(initial=False) def waiting_too_long(self): return time.time() - self.participant.vars['wait_page_arrival'] > 5*60