from otree.api import * import time c = cu doc = """ Time Sensitive Public Goods Game """ class C(BaseConstants): NAME_IN_URL = 'TS_PGG' PLAYERS_PER_GROUP = 4 NUM_ROUNDS = 4 MAX_POINTS = 10 ENDOWMENT = cu(10) MULTIPLIER = 2 CHOICES = [1,2,3,4,5,6,7,8,9,10] MAJORITY = int(PLAYERS_PER_GROUP / 2) + 1 #INSTRUCTIONS_TEMPLATE = 'TS_PGG/instructions.html' class Subsession(BaseSubsession): pass class Introduction(Page): form_model = 'player' class Group(BaseGroup): total_contribution = models.CurrencyField() individual_share = models.CurrencyField() class Player(BasePlayer): vote = models.CurrencyField() reaction_time = models.FloatField() def set_payoffs(group: Group): players = group.get_players() contributions = [p.vote for p in players] group.total_contribution = sum(contributions) group.individual_share = ( group.total_contribution * C.MULTIPLIER / C.PLAYERS_PER_GROUP ) for p in players: p.payoff = C.ENDOWMENT - p.vote + group.individual_share # PAGES class Coordinate(Page): @staticmethod def js_vars(player: Player): return dict(my_id=player.id_in_group) @staticmethod def live_method(player: Player, data): group = player.group if 'vote' in data: try: vote = int(data['vote']) except Exception: print('Invalid message received', data) return if not vote in C.CHOICES: print('Invalid message received', data) return player.vote = vote player.reaction_time=round(time.time()*1000)-data['startTime'] players = group.get_players() tallies = 0 votes = [] for p in players: vote = p.field_maybe_none('vote') if vote is not None: tallies += 1 #save response times here if tallies == 4: return {0: dict(votes=votes,tallies=tallies,finished=True)} votes.append([p.id_in_group, vote]) # if you don't want to show who voted, use 'tallies' instead of 'votes'. return {0: dict(votes=votes, tallies=tallies)} #@staticmethod #def error_message(player: Player, values): #group = player.group # anti-cheating measure #if group.field_maybe_none('contribution') is None: # return "Not done with this page" class sync_inst(Page): pass class StartWait(WaitPage): pass class ResultsWait(WaitPage): after_all_players_arrive = set_payoffs class Results(Page): pass #page_sequence = [Introduction,StartWait,Coordinate, ResultsWait, Results] page_sequence = [StartWait,Coordinate, ResultsWait, Results]