from otree.api import * from csv import reader import random class C(BaseConstants): NAME_IN_URL = 'survey' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 selected_reduced_norm_round = random.randint(1,2) selected_non_reduced_norm_round = random.randint(1,2) selected_extensive_round = random.randint(1,2) #course = ['principle', 'intermediate', 'game', 'theory', 'exp'] order = [0.9,0.75,0.4,0.6] payoff_red = { 0.4 : [150,90,230,170,310,250,390], 0.6 : [150,110,270,230,390,350,510], 0.75 : [150,125,300,275,450,425,600], 0.9 : [150,140,330,320,510,500,690], } payoff_blue = { 0.4 : [50,190,130,270,210,350,290], 0.6 : [50,210,170,330,290,450,410], 0.75 : [50,225,200,375,350,525,500], 0.9 : [50,240,230,420,410,600,590], } course = [ dict(name='principle', label="個體經濟學原理(原名:經濟學原理與實習上)"), dict(name='intermediate', label="個體經濟學"), dict(name='theory', label="個體經濟理論"), dict(name='game', label="經濟系開設之賽局相關選修課程(例如:賽局論)"), dict(name='exp', label="實驗經濟學"), # dict(name='none', label="我未曾修過以上任一門課程"), ] class Subsession(BaseSubsession): pass class Group(BaseGroup): pass def get_department_lst(): with open('_static/experiment/department_list.csv', 'r', encoding="utf-8") as f: lst = f.read().strip().split("\n") lst = [x.split(",") for x in lst] return lst # with open('_static/experiment/department_list.csv', 'r', encoding="utf-8") as csv_file: # csv_reader = reader(csv_file) # # Passing the csv_reader object to list() to get a list of lists # list_of_rows = list(csv_reader) # return list_of_rows class Player(BasePlayer): in_app_id = models.IntegerField(initial=0) # reduced normal form (rn): payoffs_reduced_norm = models.IntegerField(initial=0) oppo_payoffs_reduced_norm = models.IntegerField(initial=0) node_rn = models.IntegerField(initial=0) opponent_node_rn = models.IntegerField(initial=0) take_rn = models.IntegerField(initial=0) opponent_take_rn = models.IntegerField(initial=0) in_app_id_rn = models.IntegerField(initial=0) oppo_in_app_id_rn = models.IntegerField(initial=0) # non-reduced normal form (nrn): payoffs_non_reduced_norm = models.IntegerField(initial=0) oppo_payoffs_non_reduced_norm = models.IntegerField(initial=0) node_nrn = models.IntegerField(initial=0) opponent_node_nrn = models.IntegerField(initial=0) take1_nrn = models.IntegerField(initial=0) take2_nrn = models.IntegerField(initial=0) take3_nrn = models.IntegerField(initial=0) opponent_take1_nrn = models.IntegerField(initial=0) opponent_take2_nrn = models.IntegerField(initial=0) opponent_take3_nrn = models.IntegerField(initial=0) in_app_id_nrn = models.IntegerField(initial=0) oppo_in_app_id_nrn = models.IntegerField(initial=0) # extensive form (e): payoffs_extensive = models.IntegerField(initial=0) oppo_payoffs_extensive = models.IntegerField(initial=0) node_e = models.IntegerField(initial=0) opponent_node_e = models.IntegerField(initial=0) take_e = models.BooleanField(initial = False) opponent_take_e = models.BooleanField(initial = False) in_app_id_e = models.IntegerField(initial=0) oppo_in_app_id_e = models.IntegerField(initial=0) total_payoff = models.IntegerField(initial=0) total_payoff_with = models.IntegerField(initial=0) age = models.IntegerField(label='你的年齡是:', min=17, max=99, required = True) gender = models.StringField( choices=[['Male', '生理男'], ['Female', '生理女'], ['Other', '其他']], label='你的生理性別是:', widget=widgets.RadioSelect, required = True ) blood_type = models.StringField( choices=[['A', 'A型'], ['B', 'B型'], ['O', 'O型'], ['AB', 'AB型'], ['Other', '其他']], label='你的血型是:', required = True ) identity = models.BooleanField( choices=[['True', '台灣本地生'], ['False', '非台灣本地生(例如:僑生、外籍交換學生等)']], label='你是否為台灣本地生?', widget=widgets.RadioSelect, required = True ) grade = models.StringField( choices=[['1', '大學部1年級'], ['2', '大學部2年級'], ['3', '大學部3年級'], ['4', '大學部4年級'], ['5', '大學部5年級以上'], ['6', '碩士班'], ['7', '博士班'], ['8', '其他']], label='你的年級是:', required = True ) #from django.core.validators import MinLengthValidator #class Volume(models.Model): #department = models.CharField('Volume Number', max_length=4, validators=[MinLengthValidator(4)]) # department = models.StringField( # label='你的學號第四至七碼是:', # #max_length = 4, # required = True, # ) department = models.StringField( label='你的系所是:(如果選項裡面沒有您的系所,請舉手向實驗助手反應)', required = True, choices=get_department_lst() ) #number_of_courses = models.StringField( # choices=[['1', '個體經濟學原理(原經濟學原理與實習上)'], ['2', '個體經濟學'], ['3', '賽局論'], ['4', '個體經濟理論(僅限經濟系選修)'], ['5', '實驗經濟學']], # label='請問你目前為止修過幾堂經濟學相關課程?', #) decision_rule = models.LongStringField( label='請問在實驗過程中,你是如何決定「繼續」或「停下」?', required = True ) before_decision = models.LongStringField( label='請問你覺得你的對手是如何決定「繼續」或「停下」?', required = True ) round_decision = models.LongStringField( label='在不同的回合之間,請問你有沒有調整你的策略?為什麼?', required = True ) principle = models.BooleanField(blank=True) intermediate = models.BooleanField(blank=True) theory = models.BooleanField(blank=True) game = models.BooleanField(blank=True) exp = models.BooleanField(blank=True) none = models.BooleanField(blank=True) def graph_parameters(final_round,round,node): return dict( red1_rn = C.payoff_red[C.order[C.selected_reduced_norm_round-1]][0], red2_rn = C.payoff_red[C.order[C.selected_reduced_norm_round-1]][1], red3_rn = C.payoff_red[C.order[C.selected_reduced_norm_round-1]][2], red4_rn = C.payoff_red[C.order[C.selected_reduced_norm_round-1]][3], red5_rn = C.payoff_red[C.order[C.selected_reduced_norm_round-1]][4], red6_rn = C.payoff_red[C.order[C.selected_reduced_norm_round-1]][5], red7_rn = C.payoff_red[C.order[C.selected_reduced_norm_round-1]][6], blue1_rn = C.payoff_blue[C.order[C.selected_reduced_norm_round-1]][0], blue2_rn = C.payoff_blue[C.order[C.selected_reduced_norm_round-1]][1], blue3_rn = C.payoff_blue[C.order[C.selected_reduced_norm_round-1]][2], blue4_rn = C.payoff_blue[C.order[C.selected_reduced_norm_round-1]][3], blue5_rn = C.payoff_blue[C.order[C.selected_reduced_norm_round-1]][4], blue6_rn = C.payoff_blue[C.order[C.selected_reduced_norm_round-1]][5], blue7_rn = C.payoff_blue[C.order[C.selected_reduced_norm_round-1]][6], red1_nrn = C.payoff_red[C.order[C.selected_non_reduced_norm_round-1]][0], red2_nrn = C.payoff_red[C.order[C.selected_non_reduced_norm_round-1]][1], red3_nrn = C.payoff_red[C.order[C.selected_non_reduced_norm_round-1]][2], red4_nrn = C.payoff_red[C.order[C.selected_non_reduced_norm_round-1]][3], red5_nrn = C.payoff_red[C.order[C.selected_non_reduced_norm_round-1]][4], red6_nrn = C.payoff_red[C.order[C.selected_non_reduced_norm_round-1]][5], red7_nrn = C.payoff_red[C.order[C.selected_non_reduced_norm_round-1]][6], blue1_nrn = C.payoff_blue[C.order[C.selected_non_reduced_norm_round-1]][0], blue2_nrn = C.payoff_blue[C.order[C.selected_non_reduced_norm_round-1]][1], blue3_nrn = C.payoff_blue[C.order[C.selected_non_reduced_norm_round-1]][2], blue4_nrn = C.payoff_blue[C.order[C.selected_non_reduced_norm_round-1]][3], blue5_nrn = C.payoff_blue[C.order[C.selected_non_reduced_norm_round-1]][4], blue6_nrn = C.payoff_blue[C.order[C.selected_non_reduced_norm_round-1]][5], blue7_nrn = C.payoff_blue[C.order[C.selected_non_reduced_norm_round-1]][6], red1_e = C.payoff_red[C.order[C.selected_extensive_round-1]][0], red2_e = C.payoff_red[C.order[C.selected_extensive_round-1]][1], red3_e = C.payoff_red[C.order[C.selected_extensive_round-1]][2], red4_e = C.payoff_red[C.order[C.selected_extensive_round-1]][3], red5_e = C.payoff_red[C.order[C.selected_extensive_round-1]][4], red6_e = C.payoff_red[C.order[C.selected_extensive_round-1]][5], red7_e = C.payoff_red[C.order[C.selected_extensive_round-1]][6], blue1_e = C.payoff_blue[C.order[C.selected_extensive_round-1]][0], blue2_e = C.payoff_blue[C.order[C.selected_extensive_round-1]][1], blue3_e = C.payoff_blue[C.order[C.selected_extensive_round-1]][2], blue4_e = C.payoff_blue[C.order[C.selected_extensive_round-1]][3], blue5_e = C.payoff_blue[C.order[C.selected_extensive_round-1]][4], blue6_e = C.payoff_blue[C.order[C.selected_extensive_round-1]][5], blue7_e = C.payoff_blue[C.order[C.selected_extensive_round-1]][6], ) # FUNCTIONS # PAGES class Before_set_payoff(Page): @staticmethod def before_next_page(player, timeout_happened): participant = player.participant # update reduced normal form player.payoffs_reduced_norm = participant.payoffs_list[C.selected_reduced_norm_round - 1] player.oppo_payoffs_reduced_norm = participant.oppo_payoffs_list[C.selected_reduced_norm_round - 1] player.take_rn = participant.takes_list[C.selected_reduced_norm_round - 1] player.opponent_take_rn = participant.oppo_takes_list[C.selected_reduced_norm_round - 1] player.oppo_in_app_id_rn = participant.oppo_list[C.selected_reduced_norm_round - 1] # update non-reduced normal form player.payoffs_non_reduced_norm = participant.payoffs_list[2 + C.selected_non_reduced_norm_round - 1] player.oppo_payoffs_non_reduced_norm = participant.oppo_payoffs_list[2 + C.selected_non_reduced_norm_round - 1] player.take1_nrn = participant.takes_list[2 + C.selected_non_reduced_norm_round - 1][0] player.take2_nrn = participant.takes_list[2 + C.selected_non_reduced_norm_round - 1][1] player.take3_nrn = participant.takes_list[2 + C.selected_non_reduced_norm_round - 1][2] player.opponent_take1_nrn = participant.oppo_takes_list[2 + C.selected_non_reduced_norm_round - 1][0] player.opponent_take2_nrn = participant.oppo_takes_list[2 + C.selected_non_reduced_norm_round - 1][1] player.opponent_take3_nrn = participant.oppo_takes_list[2 + C.selected_non_reduced_norm_round - 1][2] player.oppo_in_app_id_nrn = participant.oppo_list[2 + C.selected_non_reduced_norm_round - 1] # update extensive form player.payoffs_extensive = participant.payoffs_list[4 + C.selected_extensive_round - 1] player.oppo_payoffs_extensive = participant.oppo_payoffs_list[4 + C.selected_extensive_round - 1] player.node_e = participant.nodes_list[C.selected_extensive_round-1] player.opponent_node_e = participant.oppo_nodes_list[C.selected_extensive_round-1] player.take_e = participant.takes_list[4 + C.selected_extensive_round - 1] player.opponent_take_e = participant.oppo_takes_list[4 + C.selected_extensive_round - 1] player.oppo_in_app_id_e = participant.oppo_list[4 + C.selected_extensive_round - 1] player.total_payoff = player.payoffs_reduced_norm + player.payoffs_non_reduced_norm + player.payoffs_extensive player.total_payoff_with = player.total_payoff + 200 class Payoff_red(Page): @staticmethod def is_displayed(player:Player): participant = player.participant return participant.drop == False and player.id_in_group % 2 == 1 @staticmethod def vars_for_template(player): return graph_parameters(final_round = 1,round=player.round_number, node=1) class Payoff_blue(Page): @staticmethod def is_displayed(player:Player): participant = player.participant return participant.drop == False and player.id_in_group % 2 == 0 @staticmethod def vars_for_template(player): return graph_parameters(final_round = 1,round=player.round_number, node=1) class Exp_survey1(Page): form_model = 'player' form_fields = ['age','gender','identity','grade','department', 'decision_rule','before_decision','round_decision'] @staticmethod def is_displayed(player:Player): participant = player.participant return participant.drop == False class Exp_survey2(Page): form_model = 'player' @staticmethod def get_form_fields(player: Player): return [course['name'] for course in C.course] # @staticmethod # def error_message(player: Player, values): # num_selected = 0 # for course in C.course: # if values[course['name']]: # num_selected += 1 # if num_selected < 1: # return "請勾選至少一個選項!" @staticmethod def is_displayed(player:Player): participant = player.participant return participant.drop == False class personal_account(Page): @staticmethod def is_displayed(player:Player): participant = player.participant return participant.drop == False class message(Page): @staticmethod def is_displayed(player:Player): participant = player.participant return participant.drop == True page_sequence = [ Before_set_payoff, Payoff_red, Payoff_blue, Exp_survey1, Exp_survey2, message, personal_account, ]