from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, ) import numpy as np import random import xlrd as xd author = 'Karthik' doc = """ Cry Wolf Game - High Quality Chat No Instruction Transparent """ class Constants(BaseConstants): name_in_url = 'CryWolfHighQualityTransparent' players_per_group = None show_up_fee=15.0 num_rounds = 3 # number of rounds for this game investment_instructions = 'CryWolfHighQualityTransparent/InvestmentInstructions.html' round_amount = 30.0 # amount provided for each round # cost_amount = [3.5,3.75,5.625,7.5,7.75] # amount to deduct if Take the Cost loss_amount = 22.5 # amount to deduct if Take the Risk and they lose take_risk = '冒险' take_cost = '避险' # good outcome and bad outcome payment list based on choice for investment task good_outcome = {1: 0.90, 2: 1.05, 3: 1.20, 4: 1.35, 5: 1.50, 6: 1.65, 7: 1.80, 8: 1.95, 9: 2.10, 10: 2.25} bad_outcome = {1: 0.90, 2: 0.80, 3: 0.70, 4: 0.60, 5: 0.50, 6: 0.40, 7: 0.30, 8: 0.20, 9: 0.10, 10: 0.00} # loss probability list to choose loss probability for each round given in order # loss_probabilities_list = [0.22, 0.29, 0.95, 0.84, 0.43, # 0.81, 0.72, 0.29, 0.73, 0.49, # 0.34, 0.48, 0.22, 0.56, 0.46, # 0.41, 0.49, 0.52, 0.78, 0.27, # 0.13, 0.92, 0.73, 0.74, 0.22, # 0.43, 0.53, 0.21, 0.27, 0.49, # 0.69, 0.61, 0.77, 0.77, 0.35, # 0.57, 0.45, 0.78, 0.55, 0.81, # 0.36, 0.27, 0.73, 0.15, 0.57, # 0.75, 0.48, 0.34, 0.33, 0.82] # this is the reference list that the bot advice calculation will return based on the loss probability list # and loss tokens and cost tokens specified above for each round. # This is just for reference and not used any where in the application reference = ['Take the Risk', 'Take the Risk', 'Take the Cost', 'Take the Cost', 'Take the Risk', 'Take the Cost', 'Take the Cost', 'Take the Risk', 'Take the Cost', 'Take the Risk', 'Take the Risk', 'Take the Risk', 'Take the Risk', 'Take the Risk', 'Take the Risk', 'Take the Risk', 'Take the Risk', 'Take the Risk', 'Take the Cost', 'Take the Risk', 'Take the Risk', 'Take the Cost', 'Take the Cost', 'Take the Cost', 'Take the Risk', 'Take the Risk', 'Take the Risk', 'Take the Risk', 'Take the Risk', 'Take the Risk', 'Take the Cost', 'Take the Risk', 'Take the Cost', 'Take the Cost', 'Take the Risk', 'Take the Risk', 'Take the Risk', 'Take the Cost', 'Take the Risk', 'Take the Cost', 'Take the Risk', 'Take the Risk', 'Take the Cost', 'Take the Risk', 'Take the Risk', 'Take the Cost', 'Take the Risk', 'Take the Risk', 'Take the Risk', 'Take the Cost'] class Subsession(BaseSubsession): def creating_session(self): if self.round_number == 1: # 1. 先把50个人50轮的cost和loss数据从Excel中导入到该session的list中,供后面调用 data = xd.open_workbook('_static/global/Cost_Loss5050.xlsx') # 打开excel表所在路径 Costsheet = data.sheet_by_name('Cost50') Losssheet = data.sheet_by_name('Loss50') # 读取数据,以excel表名来打开 cost_list = [] loss_list = [] for r in range(Costsheet.nrows): # 将表中数据按行逐步添加到列表中,最后转换为list结构 data1 = [] for c in range(Costsheet.ncols): data1.append(Costsheet.cell_value(r, c)) cost_list.append(list(data1)) self.session.vars['cost_list'] =cost_list # print(self.session.vars['cost_list']) for r in range(Losssheet.nrows): # 将表中数据按行逐步添加到列表中,最后转换为list结构 data2 = [] for c in range(Losssheet.ncols): data2.append(Losssheet.cell_value(r, c)) loss_list.append(list(data2)) self.session.vars['loss_list'] = loss_list # print(self.session.vars['loss_list']) #2. 再给处在第一轮的这些player分配各自的50轮cost list和loss list player_list = self.get_players() for player in player_list: my_id = player_list.index(player) # print(my_id) player.participant.lossprob_list=self.session.vars['loss_list'][my_id] # print(player.participant.loss_list) player.participant.cost_list = self.session.vars['cost_list'][my_id] # print(player.participant.cost_list) # 每一组的收益都由上一组的决策决定,第一组(即group id为0的组)由最后一组决定 # if my_group_id == 0: # othergroup = group_list[-1] # self.group.other_group_id = group_list[-1].id_in_subsession # self.group.other_group_X = group_list[-1].decision_X # self.group.other_group_Y = group_list[-1].decision_Y class Group(BaseGroup): pass # loss_probability = models.FloatField(min=0, max=1) # bot_advice = models.CharField() # # def calculate_advice(self): # # if random.random()<0.5: # # # # else: # advice = Constants.take_risk # if (Constants.loss_amount * self.loss_probability) > np.mean(Constants.cost_amount): # advice = Constants.take_cost # return advice # # def calculate_random_advice(self): # advice = random.choice([Constants.take_risk, Constants.take_cost]) # return advice class Player(BasePlayer): risk_result =models.FloatField(min=0) cost_result = models.FloatField(min=0) decision_taken = models.CharField(widget=widgets.RadioSelect(), choices=['冒险', '避险']) decision_number = models.PositiveIntegerField() bot_advice_number = models.PositiveIntegerField() final_payoff=models.FloatField(min=0) random_number_generated = models.FloatField(min=0, max=1) amount_won_in_round = models.FloatField(min=Constants.round_amount-Constants.loss_amount, max=Constants.round_amount) paying_round = models.PositiveIntegerField(min=1, max=Constants.num_rounds) # investment_chosen = models.PositiveIntegerField(widget=widgets.RadioSelectHorizontal(), # choices=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) # investment_outcome = models.CharField() # investment_pay = models.FloatField(min=0.0, max=0.9) loss_probability = models.FloatField(min=0, max=1) cost = models.FloatField(min=0) bot_advice = models.CharField() def calculate_advice(self): # if random.random()<0.5: # # else: advice = Constants.take_risk # cost_result表示take cost的本轮收益 self.risk_result = Constants.round_amount *(1 - self.loss_probability) +(Constants.round_amount - Constants.loss_amount) * (self.loss_probability) self.cost_result = Constants.round_amount - self.cost if self.risk_result < self.cost_result: #不等式左边是冒险的收益,右边是避险的 advice = Constants.take_cost return advice def calculate_random_advice(self): advice = random.choice([Constants.take_risk, Constants.take_cost]) return advice def set_payoffs(self): self.amount_won_in_round = Constants.round_amount if self.decision_taken == '避险': self.decision_number = 2 self.amount_won_in_round = Constants.round_amount - self.cost # self.amount_won_in_round = Constants.round_amount - random.choice(Constants.cost_amount) else: self.decision_number = 1 if self.random_number_generated <= self.loss_probability: self.amount_won_in_round = Constants.round_amount - Constants.loss_amount else: self.amount_won_in_round = Constants.round_amount def total_payoffs(self): self.final_payoff = self.in_round(self.paying_round).amount_won_in_round + Constants.show_up_fee # self.investment_pay = Constants.bad_outcome[self.investment_chosen] # if self.investment_outcome == 'Good': # self.investment_pay = Constants.good_outcome[self.investment_chosen] # self.payoff = round(self.in_round(self.paying_round).amount_won_in_round + self.investment_pay)