from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import random doc = """ Двойной аукцион. """ class Constants(BaseConstants): name_in_url = 'buyer_seller' players_per_group = 2 num_rounds = 2 instructions_template = 'buyer_seller/instructions.html' TotalResult_template = 'buyer_seller/AdminReport.html' class Subsession(BaseSubsession): def creating_session(self): self.group_randomly(fixed_id_in_group=True) if self.round_number % 2 == 1: pl_matrix = self.get_group_matrix() for row in pl_matrix: row.reverse() self.set_group_matrix(pl_matrix) print(self.get_group_matrix()) def get_active_players(self): return [p for p in self.get_players() if p.is_alive()] def do_my_shuffle(self): newlist = [p for p in self.get_players() if p.is_alive()] leftlist = [p for p in self.get_players() if not p.is_alive()] pcount = len(newlist) num_to_add = Constants.players_per_group - pcount % Constants.players_per_group if num_to_add < Constants.players_per_group: newlist += leftlist[:num_to_add] leftlist = leftlist[num_to_add:] pcount = len(newlist) nums = random.SystemRandom().sample(range(pcount), pcount) shufflelist = [newlist[i] for i in nums]+leftlist gr_matrix = [shufflelist[i:i+Constants.players_per_group] for i in range(0, len(shufflelist), Constants.players_per_group)] self.set_group_matrix(gr_matrix) def vars_for_admin_report(self): subs_avg1 = [] for subs in self.in_all_rounds(): pl_seller = 2*sum((p.group.seller_price-p.fx()) if (p.id_in_group == 1) else 0 for p in subs.get_players())/len(subs.get_players()) pl_buyer = 2*sum((-p.group.buyer_price+p.fx()) if (p.id_in_group == 2) else 0 for p in subs.get_players())/len(subs.get_players()) subs_avg1.append(round(pl_seller,1)) subs_avg2 = [] for subs in self.in_all_rounds(): pl_seller = 2*sum((p.group.seller_price-p.fx()) if (p.id_in_group == 1) else 0 for p in subs.get_players())/len(subs.get_players()) pl_buyer = 2*sum((-p.group.buyer_price+p.fx()) if (p.id_in_group == 2) else 0 for p in subs.get_players())/len(subs.get_players()) subs_avg2.append(round(pl_buyer,1)) series = [] for player in self.get_players(): pl_id = player.participant.id_in_session name = player.participant.label pl_totalpay = sum(p.float_payoff for p in player.in_all_rounds()) pl_seller = sum(p.group.seller_price-p.fx() if (p.id_in_group == 1) else 0 for p in player.in_all_rounds())/sum((p.id_in_group == 1) for p in player.in_all_rounds()) pl_buyer = sum(-p.group.buyer_price+p.fx() if (p.id_in_group == 2) else 0 for p in player.in_all_rounds())/sum((p.id_in_group == 2) for p in player.in_all_rounds()) series.append(dict ( ID = pl_id, Name = name, TotalPay = pl_totalpay, Seller = pl_seller, Buyer = pl_buyer)) cnt = len(series) if cnt>0: av = dict (ID = 0, Name = 'AVG', TotalPay = round(sum(s['TotalPay'] for s in series)/cnt,0), Seller = round(sum(s['Seller'] for s in series)/cnt,2), Buyer = round(sum(s['Buyer'] for s in series)/cnt,2)) series.insert(0, av) return dict( game_data=series, period_data1 = subs_avg1, period_data2 = subs_avg2, round_numbers=list(range(1, len(subs_avg1) + 1))) class Group(BaseGroup): buyer_price = models.FloatField( min=0, default=0) seller_price = models.FloatField( max=100, default=0) def buyer_price_max(self): return self.get_player_by_id(2).x def seller_price_min(self): return self.get_player_by_id(1).x def set_payoffs(self): p1 = self.get_player_by_id(1) p2 = self.get_player_by_id(2) price = 0.5*(self.buyer_price + self.seller_price) p1.payoff = price - p1.x if self.seller_price<=self.buyer_price else 0 p2.payoff = p2.x - price if self.seller_price<=self.buyer_price else 0 class Player(BasePlayer): x = models.IntegerField(initial=None) float_payoffs = models.FloatField( min=0, default=0) def fx(self): if self.x == None: self.x = random.randint(0,60) if self.id_in_group == 1 else random.randint(40,100) return self.x def is_alive(self): return not ((self.participant.label is None) or (self.participant.label == "")) def role(self): return {1: 'A', 2: 'B'}[self.id_in_group] def other_player(self): return self.get_others_in_group()[0] def f_payoffs(self): price = 0.5*(self.group.buyer_price + self.group.seller_price) payoff1 = price - self.x if self.group.seller_price<=self.group.buyer_price else 0 payoff2 = self.x - price if self.group.seller_price<=self.group.buyer_price else 0 self.float_payoffs = payoff1 if self.id_in_group == 1 else payoff2 return self.float_payoffs