from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) from random import randint author = 'Your name here' doc = """ Your app description """ class Constants(BaseConstants): name_in_url = 'auctionGame' players_per_group = 2 num_rounds = 35 #time_to_wait = 30 number_periods = 7 startPriceOperations = [9, 6, 10, 7, 11, 8, 12] startPriceSales = [13, 10, 14, 11, 15, 12, 16] deltaPrice = 1 class Subsession(BaseSubsession): pass class Group(BaseGroup): price_op = models.IntegerField() price_sales = models.IntegerField() excessDemand = models.IntegerField(initial = 99) priceEquilibrium = models.BooleanField(initial = False) certainty = models.BooleanField() finalQuantity = models.IntegerField(initial = 0) inputSales = models.IntegerField() inputOp = models.IntegerField() countRounds = models.IntegerField() rdmRound_sales = models.IntegerField() rdmRound_operations = models.IntegerField() rdmCurve_sales = models.IntegerField() rdmCurve_operations = models.IntegerField() reward_Sales = models.IntegerField() reward_Operations = models.IntegerField() def ShowRound(self): return self.countRounds + 1 def RdmRound(self): rdmRound = randint(1, Constants.number_periods) players = self.get_players() for p in players: if p.role() == "Sales": self.rdmRound_sales = rdmRound print(self.rdmRound_sales) else: self.rdmRound_operations = rdmRound return rdmRound def UpdatePrice(self): if self.round_number == 1: self.countRounds = 0 #print("session config: " + str(self.session.config['treatment'])) self.priceEquilibrium = False self.price_op = Constants.startPriceOperations[self.countRounds] self.price_sales = Constants.startPriceSales[self.countRounds] else: excessDemand = self.LastInputSales() - self.LastInputOp() lastPriceSales = self.LastPriceSales() lastPriceOp = self.LastPriceOp() # check if a new round needs to start if [g.priceEquilibrium for g in self.in_previous_rounds()][-1] == True: self.countRounds = self.LastRoundNumber() + 1 self.price_op = Constants.startPriceOperations[self.countRounds] self.price_sales = Constants.startPriceSales[self.countRounds] self.priceEquilibrium = False else: self.countRounds = self.LastRoundNumber() #self.session.config['treatment'] = self.session.config['treatment'] + 1 #print("session config: " + str(self.session.config['treatment'])) if excessDemand < 0: self.price_sales = lastPriceSales - Constants.deltaPrice self.price_op = lastPriceOp else: self.price_op = lastPriceOp + Constants.deltaPrice self.price_sales = lastPriceSales def WinningCondition(self): players = self.get_players() for p in players: if p.role() == "Sales": self.inputSales = p.countUnits else: self.inputOp = p.countUnits self.excessDemand = self.inputSales - self.inputOp if self.price_op == self.price_sales: self.finalQuantity = min(self.inputSales, self.inputOp) self.CalculatePayoff(self.finalQuantity) self.priceEquilibrium = True print("end game") def LastRoundNumber(self): priceList = [g.countRounds for g in self.in_previous_rounds()] return priceList[-1] def LastInputSales(self): priceList = [g.inputSales for g in self.in_previous_rounds()] return priceList[-1] def LastInputOp(self): priceList = [g.inputOp for g in self.in_previous_rounds()] return priceList[-1] def LastPriceSales(self): priceList = [g.price_sales for g in self.in_previous_rounds()] return priceList[-1] def LastPriceOp(self): priceList = [g.price_op for g in self.in_previous_rounds()] return priceList[-1] def UnitsSold(self): unitsSoldList = [g.finalQuantity for g in self.in_previous_rounds()] return unitsSoldList[-1] def CurveOperation(self, rand, quant): price_list = [] offset = 0 X1 = Constants.startPriceOperations[self.countRounds] if quant == 0: return [0] if self.certainty == False: if rand == 1: offset = 1 else: offset -1 for i in range(quant): price_list.append(X1 + i + offset) return price_list def CurveSales(self, rand, quant): price_list = [] offset = 0 X1 = Constants.startPriceSales[self.countRounds] print(X1) if self.certainty == False: if rand == 1: offset = 1 else: offset -1 if quant == 0: if self.certainty == False: return [X1 + 1 + offset] for i in range(quant): if (X1 - i + offset > 0): if i < 5: price_list.append(X1 - i + offset) else: price_list.append(0) else: continue return price_list def CalculatePayoff(self, finalQuant): # save random choice in data 0 in certainty case, 1 in +1 shift, -1 for -1 shift if self.certainty == False: self.rdmCurve_sales = randint(-1, 1) self.rdmCurve_operations = randint(-1, 1) else: self.rdmCurve_sales = 0 self.rdmCurve_operations = 0 unit_price_sales = self.CurveSales(self.rdmCurve_sales, finalQuant) unit_price_operation = self.CurveOperation(self.rdmCurve_operations, finalQuant) #print("Sales: " + str(unit_price_sales)) #print("Operation: " + str(unit_price_operation)) price_shown_operation = [g.price_op for g in self.in_all_rounds()][-5:] #print("price operations" + str(price_shown_operation)) price_shown_sales = [g.price_sales for g in self.in_all_rounds()][-5:] #print("price sales" + str(price_shown_sales)) list_sales = [g.inputSales for g in self.in_all_rounds()][-5:] #print("list sales: " + str(list_sales)) list_op = [g.inputOp for g in self.in_all_rounds()][-5:] #print("list op: " + str(list_op)) list_cum_sales = [] list_cum_op = [] cum_clinch_sales = [] cum_clinch_op = [] rew_op = [] rew_sales = [] for i in range (len(list_sales)): list_cum_sales.append(min(finalQuant, list_sales[i])) list_cum_op.append(min(finalQuant, list_op[i])) if i == 0: cum_clinch_sales.append(list_cum_sales[i]) cum_clinch_op.append(list_cum_op[i]) else: cum_clinch_sales.append(list_cum_sales[i]-list_cum_sales[i-1]) cum_clinch_op.append(list_cum_op[i]-list_cum_op[i-1]) rew_op.append(price_shown_operation[i] * cum_clinch_op[i]) rew_sales.append(price_shown_sales[i] * cum_clinch_sales[i]) #print(list_cum_sales) #print(list_cum_op) #print(cum_clinch_sales) #print(cum_clinch_op) #print(rew_op) #print(rew_sales) #print(sum(rew_op)) #print(sum(rew_sales)) self.reward_Sales = sum(unit_price_sales) - sum(rew_op) if self.reward_Sales < 0: self.reward_Sales = 0 self.reward_Operations = sum(rew_sales) - sum(unit_price_operation) if self.reward_Operations < 0: self.reward_Operations = 0 class Player(BasePlayer): countUnits = models.IntegerField(min = 0, max = 9999999) def action(self): if self.id_in_group == 1: return 'buy' else: return 'sell' def verbAction(self): if self.id_in_group == 1: return 'bidding' else: return 'asking' def actionIntro(self): if self.id_in_group == 1: return 'bid' else: return 'ask' def role(self): if self.id_in_group == 1: return 'Sales' else: return 'Operations'