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 author = 'Jindi Huang' doc = """ Game Complexity """ class Constants(BaseConstants): name_in_url = 'game' players_per_group = 2 num_rounds = 3 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: category = itertools.cycle(['fp']) for player in self.get_players(): player.participant.vars['category'] = next(category) player.participant.vars['failed_comprehension'] = False player.participant.vars['payround'] = random.randint(1, Constants.num_rounds) player.participant.vars['game_payment'] = 0 player.participant.vars['total_payment'] = 0 self.group_randomly() 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): d = defaultdict(list) for p in waiting_players: category = p.participant.vars['category'] players_with_this_category = d[category] players_with_this_category.append(p) if len(players_with_this_category) == Constants.players_per_group: return players_with_this_category 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() # bid5 = models.CurrencyField() def set_payoffs(self): players = self.get_players() bids = [p.bid for p in players if p.bid != None] bids.sort(reverse=True) if len(bids) != 0: self.bid1 = bids[0] if len(bids) > 1: self.bid2 = bids[1] if (len(bids) > 1 and bids[0] == bids[1]) or len(bids) == 0: 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 == bids[0]: player.winner = 1 if player.current_play == 'fp': player.round_payoff = player.signal - bids[0] else: if len(bids) == 1: player.round_payoff = player.signal else: player.round_payoff = player.signal - bids[1] 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 - bids[0] else: player.winner = 0 player.round_payoff = c(0) for player in players: if self.round_number == player.participant.vars['payround']: player.game_payment = player.round_payoff + self.session.config['baseline_bonus'] player.participant.vars['game_payment'] = player.game_payment player.total_payment = player.game_payment + self.session.config['participation_fee'] player.participant.vars['total_payment'] = player.total_payment class Player(BasePlayer): bid = models.CurrencyField(label=False, blank=True) signal = models.CurrencyField() current_play = models.StringField() round_payoff = models.CurrencyField() confidence = models.FloatField() winner = models.IntegerField() total_payment = models.CurrencyField() game_payment = models.CurrencyField() prolific_id = models.StringField() bid_help = models.FloatField(blank=True) stop_help = models.IntegerField(blank=True) question_failed = models.IntegerField() failed_comprehension = models.BooleanField(initial=False) qn_lottery_got_wrong = models.BooleanField(initial=False) qn_list_got_wrong = models.BooleanField(initial=False) qn_confidence_got_wrong = models.BooleanField(initial=False) qn_lottery = models.IntegerField( choices=[ [0, 'It would be possible that I get BOTH the lottery ticket and $7.00.'], [1, 'I would receive EITHER the lottery ticket OR $7.00.'], [0, 'If I choose to keep the lottery ticket, I would receive $10.00 for sure.'], ], widget=widgets.RadioSelect, blank=False, label="" ) qn_list = models.IntegerField( choices=[ [0, 'This person indicated that the lottery ticket would be worth more to them than $7.00.'], [0, 'This person indicated that the lottery ticket would be worth between $8.00 and $8.50 to them.'], [1, 'This person indicated that the lottery ticket would be worth between $6.50 and $7.00 to them.'], ], widget=widgets.RadioSelect, blank=False, label="" ) qn_confidence = models.FloatField( blank=False, label="" ) def set_current_play(self): if self.participant.vars['category'] == 'fp' and self.round_number <= Constants.num_rounds / 3: self.current_play = 'fp' if self.participant.vars['category'] == 'fp' and self.round_number > Constants.num_rounds/3 and self.round_number <= 2*Constants.num_rounds/3: self.current_play = 'sp' if self.participant.vars['category'] == 'fp' and self.round_number > 2*Constants.num_rounds/3: self.current_play = 'aa' if self.participant.vars['category'] == 'sp' and self.round_number <= Constants.num_rounds / 3: self.current_play = 'sp' if self.participant.vars['category'] == 'sp' and self.round_number > Constants.num_rounds / 3 and self.round_number <= 2 * Constants.num_rounds / 3: self.current_play = 'aa' if self.participant.vars['category'] == 'sp' and self.round_number > 2 * Constants.num_rounds / 3: self.current_play = 'fp' if self.participant.vars['category'] == 'aa' and self.round_number <= Constants.num_rounds / 3: self.current_play = 'aa' if self.participant.vars['category'] == 'aa' and self.round_number > Constants.num_rounds / 3 and self.round_number <= 2 * Constants.num_rounds / 3: self.current_play = 'fp' if self.participant.vars['category'] == 'aa' and self.round_number > 2 * Constants.num_rounds / 3: self.current_play = 'sp' def live_aa(self, bid): stop = 0 if bid == 999: self.group.aa_stop += 1 if self.group.aa_stop >= Constants.players_per_group - 1: stop = 1 response = dict(price=bid, stop=stop) 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."