from otree.api import * import numpy as np import random import time doc = """ interactive_aggregation """ class C(BaseConstants): NAME_IN_URL = 'aggregation_tasks_treatmentI' PLAYERS_PER_GROUP = 3 BALLS_PER_URN = 100 NUM_ROUNDS = 2 INSTRUCTIONS_TEMPLATE = 'interactive_aggregation/instructions.html' class Subsession(BaseSubsession): pass class Group(BaseGroup): computer_choice = models.StringField() game_iteration = models.IntegerField(initial = 1) whose_turn = models.IntegerField(initial = 1) game_over = models.BooleanField(initial = False) urn_left = models.StringField() urn_right = models.StringField() black_left = models.IntegerField() black_right = models.IntegerField() p = models.FloatField() startTime = models.IntegerField() timeSpent = models.IntegerField() def group_start(self): self.p = self.session.config["parameters"][str(self.round_number)]["p"] self.black_left = self.session.config["parameters"][str(self.round_number)]["black_num_left"] self.black_right = self.session.config["parameters"][str(self.round_number)]["black_num_right"] toss = random.randint(0, 1) if (toss == 1): self.p = round(1 - self.p, 2) self.black_left, self.black_right = self.black_right, self.black_left # Assign balls in the left urn list_left = ["black"] * self.black_left + ["red"] * (C.BALLS_PER_URN - self.black_left) list_left = np.random.permutation(list_left).tolist() self.urn_left = ",".join(list_left) # Assign balls in the right urn list_right = ["black"] * self.black_right + ["red"] * (C.BALLS_PER_URN - self.black_right) list_right = np.random.permutation(list_right).tolist() self.urn_right = ",".join(list_right) def get_urn_balls_dict(self, label): if label != "left" and label != "right": return dict() urn = self.urn_left if label == "left" else self.urn_right balls = urn.split(",") dict = {} for i,ball in enumerate(balls): dict[i] = ball return dict def report_history(self): dict = {} for p in self.get_players(): reports = p.report_dict() for i in range(1, self.session.config["stages"] + 1): cell_id = cell_id = "#" + "cell_" + str(i) + "_" + str(p.id_in_group) if i in reports: dict[cell_id] = reports[i] return dict class Player(BasePlayer): report = models.LongStringField(initial = "") signal = models.StringField() score = models.FloatField() selected_task = models.IntegerField(initial = 0) def list_init(self, len): report_list = [""] * len self.report = ",".join(report_list) return def set_list_element(self, i, value): #index range[1, len + 1] report_list = self.report.split(",") report_list[i - 1] = str(value) self.report = ",".join(report_list) return def get_list_element(self, i): #index range[1, len + 1] report_list = self.report.split(",") return float(report_list[i - 1]) def report_dict(self): report_list = self.report.split(",") dict = {} for i,report in enumerate(report_list): if report != "": dict[i + 1] = report return dict # PAGES # class Ready(Page): # @staticmethod # def js_vars(player: Player): # return dict(num_players = C.PLAYERS_PER_GROUP) class WaittoStart(WaitPage): @staticmethod def after_all_players_arrive(group: Group): group.group_start() class SettingUp(Page): @staticmethod def js_vars(player: Player): return dict(task_number = player.round_number, p = player.group.p, pR = round(1 - player.group.p, 2), black_num = {"Left" : player.group.black_left, "Right": player.group.black_right}, urn_balls = {"Left" : player.group.get_urn_balls_dict("left"), "Right": player.group.get_urn_balls_dict("right")}) class WaittoReport(WaitPage): @staticmethod def after_all_players_arrive(group: Group): p = group.p group.computer_choice = random.choices(["left", "right"], [p, 1-p], k = 1)[0] nB = group.black_left if group.computer_choice == 0 else group.black_right nR = C.BALLS_PER_URN - nB for player in group.get_players(): player.signal = random.choices(["black", "red"], [nB, nR], k = 1)[0] player.list_init(group.session.config["stages"]) group.startTime = int(time.time()) class Report(Page): @staticmethod def js_vars(player: Player): return dict(my_id = player.id_in_group, task_number = player.round_number, round = player.session.config["stages"], game_iteration = player.group.game_iteration, whose_turn = player.group.whose_turn, num_players = C.PLAYERS_PER_GROUP, signal = player.signal, p = player.group.p, pR = round(1 - player.group.p, 2), black_num = {"Left" : player.group.black_left, "Right": player.group.black_right}, urn_balls = {"Left" : player.group.get_urn_balls_dict("left"), "Right": player.group.get_urn_balls_dict("right")}, computer_choice = player.group.computer_choice, table_content = player.group.report_history()) @staticmethod def live_method(player: Player, report): group = player.group session = player.session my_id = player.id_in_group input_hint = None if (report != None and 0 <= report and report <= 1 and group.whose_turn == my_id): player.set_list_element(group.game_iteration, report) news = dict(iteration = group.game_iteration, player_id = my_id, report = report, cell_id = "#" + "cell_" + str(group.game_iteration) + "_" + str(my_id)) if my_id == C.PLAYERS_PER_GROUP: group.whose_turn = 1 group.game_iteration = group.game_iteration + 1 if group.game_iteration > session.config["stages"]: group.game_over = True else: group.whose_turn = my_id + 1 else: news = None if (report == None): input_hint = "请输入球来自左边箱子的概率。" elif (0 > report or report > 1): input_hint = "球来自左边箱子的概率应当是0到1之间的小数。" return { 0: dict( game_iteration = group.game_iteration, game_over = group.game_over, whose_turn = group.whose_turn, news = news, input_hint = input_hint, ) } @staticmethod def before_next_page(player: Player, timeout_happened): if player.id_in_group == 1: group = player.group group.timeSpent = int(time.time()) - group.startTime class Score(Page): @staticmethod def is_displayed(player: Player): if (player.round_number == C.NUM_ROUNDS): if (player.selected_task == 0): player.selected_task = random.randrange(0, C.NUM_ROUNDS) + 1 return player.round_number == C.NUM_ROUNDS @staticmethod def js_vars(player: Player): mplayer = player.in_round(player.selected_task) value = 0 gold = 1 if mplayer.group.computer_choice == "left" else 0 score = {} for i in range(0, mplayer.session.config["stages"]): xi = mplayer.get_list_element(i + 1) value = round(value + 1 - (xi - gold) ** 2, 4) score["score_" + str(i + 1)] = round(1 - (xi - gold) ** 2, 4) return dict(total_score = value, score = score, computer_choice = mplayer.group.computer_choice, task_number = mplayer.round_number, round = mplayer.session.config["stages"], my_id = mplayer.id_in_group, p = player.group.p, pR = round(1 - player.group.p, 2), black_num = {"Left" : mplayer.group.black_left, "Right": mplayer.group.black_right}, urn_balls = {"Left" : mplayer.group.get_urn_balls_dict("left"), "Right": mplayer.group.get_urn_balls_dict("right")}, table_content = mplayer.group.report_history() ) page_sequence = [WaittoStart, SettingUp, WaittoReport, Report, Score]