class Player(markets_models.Player): current_bid = models.ForeignKey(Order, null=True, on_delete=models.CASCADE, related_name="+") current_ask = models.ForeignKey(Order, null=True, on_delete=models.CASCADE, related_name="+") width = models.IntegerField(initial=100, blank=True) cost = models.FloatField(initial=0, blank=True) m_low = models.FloatField(initial=0, blank=True) m_high = models.FloatField(initial=100, blank=True) low_val = models.FloatField(initial=0, blank=True) high_val = models.FloatField(initial=100, blank=True) round_payoff = models.FloatField(initial=100, blank=True) bonds_held = models.IntegerField(initial = 0, blank = True) e = models.FloatField(initial = 0, blank = True) # allow negative settled def check_available(self, is_bid: bool, price: int, volume: int, asset_name: str): return True def asset_endowment(self): return self.subsession.config.asset_endowment def cash_endowment(self): return 0 def custom_export(self, players): # header row print(players.values_list()) yield ['width', 'cost', 'm_low', 'm_high', 'low_val', 'high_val', 'bid_price', 'bought', 'sold', 'round_payoff', 'bonds_held'] for p in players: yield [p.width, p.bid_price, p.ask_price, p.bought, p.sold, p.round_payoff]
class Player(markets_models.Player): current_bid = models.ForeignKey(Order, null=True, on_delete=models.CASCADE, related_name="+") current_ask = models.ForeignKey(Order, null=True, on_delete=models.CASCADE, related_name="+") @property def config(self): config_name = self.session.config['session_config_file'] return MarketConfig.get(config_name, self.round_number, self.id_in_group) def utility_function(self, x, y): return eval(self.config.utility_function, {'x': x, 'y': y}) def set_payoff(self): config = self.config initial_utility = self.utility_function(config.x_endowment, config.y_endowment) current_x = self.settled_assets[ markets_models.SINGLE_ASSET_NAME] / config.x_currency_scale current_y = self.settled_cash / config.y_currency_scale current_utility = self.utility_function(current_x, current_y) initial_payoff = initial_utility * config.payoff_initial_multiplier gains_payoff = (current_utility - initial_utility) * config.payoff_gain_multiplier gains_payoff = max(gains_payoff, -initial_utility) self.payoff = (initial_payoff + gains_payoff) * 1000 def get_unscaled_payoff(self): return float(self.payoff) / 1000 def asset_endowment(self): config = self.config return config.x_endowment * config.x_currency_scale def cash_endowment(self): config = self.config return config.y_endowment * config.y_currency_scale def check_available(self, is_bid, price, volume, asset_name): '''since each player can only ever have one order entered at a time, we ignore available holdings when determining whether an order can be entered''' if is_bid and self.settled_cash < price * volume: return False elif not is_bid and self.settled_assets[asset_name] < volume: return False return True
class Message(models.Model): content = models.TextField() timestamp = django_models.DateTimeField(auto_now=True) player = models.ForeignKey('Player', on_delete=models.CASCADE, null=True) chat_id = models.IntegerField() group = models.ForeignKey('Group', on_delete=models.CASCADE, null=True) player_name = models.StringField() @staticmethod def last_30_messages(): last_30 = Message.objects.order_by('-timestamp')[:30] return reversed(last_30)
class Choice(models.Model): question = models.ForeignKey(Question, on_delete=models.CASCADE) choice_text = models.StringField(max_length=200) votes = models.IntegerField(default=0) def __str__(self): return self.choice_text
class Group(BaseGroup): network = models.ForeignKey(Network, default=1) def set_payoffs(self): for p in self.get_players(): if p.participate: group_nodes = p.node.network.node_set.all() n_participants = 0 for node in group_nodes: if node.participate: n_participants += 1 if p.threshold < n_participants: p.round_payoff = self.session.config[ 'payoff_above_threshold'] else: p.round_payoff = self.session.config[ 'payoff_below_threshold'] else: p.round_payoff = self.session.config['payoff_no_participate'] if self.subsession.round_number == int( self.session.config['payoff_round']): p.payoff = p.round_payoff pass
class PrivateMessage(models.Model): wall = models.ForeignKey(PrivateMessageBoard) createdBy = models.ForeignKey(Node) datetime = models.DateTimeField(auto_now=True) message = models.CharField() messageRound = models.IntegerField() deleted = models.BooleanField(initial=False) key = models.CharField() def to_dict(self): return { 'id': self.id, 'timestamp': self.datetime.strftime("%Y-%m-%d %H:%M:%S"), 'content': self.message, 'author': 'Player {}'.format(self.createdBy_id), 'messageRound': self.messageRound, 'key': self.key, }
class Node(models.Model): bot = models.BooleanField() avatar = models.ForeignKey( Avatar, db_column='avatar', default=1, related_name='avatar_node', ) position = models.IntegerField() network = models.ForeignKey(Network) threshold = models.FloatField(default=-1) threshold_text = models.CharField() participate = models.BooleanField() def get_neighbors(self): results = Edge.objects.filter(node_from=self) neighbors = [r.node_to for r in results] return neighbors def __str__(self): return 'P: {} - T: {}'.format(self.position, self.threshold)
class Group(BaseGroup): network = models.ForeignKey(Network, default=1) def set_payoffs(self): for p in self.get_players(): nMessages = 0 if self.session.config['condition_messaging'] == 'wall': table = p.get_entry_table() for v in table: nMessages += int(v['0']) nMessages += int(v['1']) if self.session.config['condition_messaging'] == 'bilateral': table = p.get_private_entry_table() for v in table: nMessages += int(v['0']) nMessages += int(v['1']) cost = nMessages * int( self.session.config['payoff_message_penalty']) p.message_cost = cost if p.participate: group_nodes = p.node.network.node_set.all() n_participants = 0 for node in group_nodes: if node.participate: n_participants += 1 if p.threshold < n_participants: p.round_payoff = self.session.config[ 'payoff_above_threshold'] - p.message_cost else: p.round_payoff = self.session.config[ 'payoff_below_threshold'] - p.message_cost else: p.round_payoff = self.session.config[ 'payoff_no_participate'] - p.message_cost p.round_payoff = max([p.round_payoff, 0]) if self.subsession.round_number == int( self.session.config['payoff_round']): p.payoff = p.round_payoff pass
class Risk(djmodels.Model): player = models.ForeignKey(Player, related_name="risks") left_col = models.IntegerField() right_col = models.IntegerField() answer = models.BooleanField(null=True, doc='False - option A, True - option B', widget=widgets.RadioSelectHorizontal) def __str__(self): answer_to_str = None if self.answer == True: answer_to_str = 'Option B' elif self.answer == False: answer_to_str = 'Option A' return 'choosing between option A({}) and B({}) with the probs {}/{} {} was chosen'.format( Constants.risk_choices_A, Constants.risk_choices_B, self.left_col, self.right_col, answer_to_str, )
class AdminChatMessage(models.Model): class Meta: index_together = ['channel', 'timestamp'] # the name "channel" here is unrelated to Django channels channel = models.CharField(max_length=255) # related_name necessary to disambiguate with otreechat add on participant = models.ForeignKey('otree.Participant', related_name='admin_chat_messages', on_delete=models.CASCADE) nickname = models.CharField(max_length=255) # call it 'body' instead of 'message' or 'content' because those terms # are already used by channels body = models.TextField() timestamp = models.FloatField(default=time.time) is_seen = models.BooleanField(default=False)
class Player(BasePlayer): money = models.IntegerField() cost = models.IntegerField() last_offer = models.IntegerField() trade_price = models.IntegerField() match_with = models.ForeignKey('Player', null=True, on_delete=models.CASCADE) match_with_player_id_in_group = models.IntegerField() instructions_da1 = models.IntegerField( verbose_name="You are a buyer. Your valuation for the good is 50 points. You submit a bid of 40 points and a seller accepts this bid. What are your earnings (in points)?", ) instructions_da3 = models.IntegerField( verbose_name="You are a seller. Your production costs for the good are 20 points. You submit an ask of 25 points and a buyer accepts this ask. What are your earnings (in points)?", ) instructions_da4 = models.IntegerField( verbose_name="You are a buyer. Your valuation for the good is 40 points. Is it possible to submit a bid of 60 points?", **Constants.quiz_radio_button ) display_id = models.IntegerField() is_bot = models.BooleanField()
class PrivateMessageBoard(models.Model): subsession = models.ForeignKey(Subsession) node = models.ForeignKey(Node)
class Wall(models.Model): subsession = models.ForeignKey(Subsession) node = models.ForeignKey(Node)
class Player(BasePlayer): def get_messages(self): wall = self.node.wall_set.first() if self.session.config['instant_messaging'] == 'True': wall_messages = wall.message_set.all() else: p = self.group.get_player_by_id(1) messageRound = p.participant.vars['message_round'] past_wall_messages = wall.message_set.filter( messageRound__lt=messageRound) past_wall_messages = past_wall_messages.exclude(deleted=True) posted_wall_messages = wall.message_set.filter(createdBy=self.node) posted_wall_messages = posted_wall_messages.exclude(deleted=True) wall_messages = past_wall_messages | posted_wall_messages wall_out = [m.to_dict() for m in wall_messages] return wall_out def get_private_messages(self): pmb = self.node.privatemessageboard_set.first() if self.session.config['instant_messaging'] == 'True': private_messages = pmb.privatemessage_set.all() else: p = self.group.get_player_by_id(1) messageRound = p.participant.vars['message_round'] private_messages = pmb.privatemessage_set.filter( messageRound__lt=messageRound) pmb_out = [m.to_dict() for m in private_messages] return pmb_out def get_neighbors(self): results = Edge.objects.filter(node_from=self.node) # neighbors = [Player.objects.get(node=r.node_to) for r in results] neighbors = [r.node_to for r in results] return neighbors def get_avatar(self): return self.avatar.src def get_user_name(self): return self.user_name node = models.ForeignKey(Node, default=1) threshold = models.IntegerField() participate = models.BooleanField(verbose_name="Will you participate?") # Avatar Portions user_name = models.CharField(default='Not Assigned') avatar = models.ForeignKey(Avatar, default=1, related_name='practice_avatar_seq') # Round_Payoff round_payoff = models.CurrencyField() continue_practice = models.BooleanField( verbose_name="Would you like to continue with practice rounds?", blank=True, initial=True, choices=[ [True, "Yes, I would like to continue practicing."], [ False, "No, I understand the game and would like to advance to the next step." ], ])
class Player(markets_models.Player): current_bid = models.ForeignKey(Order, null=True, on_delete=models.CASCADE, related_name="+") current_ask = models.ForeignKey(Order, null=True, on_delete=models.CASCADE, related_name="+") def check_available(self, is_bid, price, volume, asset_name): '''instead of checking available assets, just check settled assets since there can only ever be one bid/ask on the market from each player ''' if not is_bid and self.settled_assets[asset_name] < volume: return False return True def update_holdings_trade(self, price, volume, is_bid, asset_name): if is_bid: self.settled_cash -= price * volume self.available_assets[asset_name] += volume self.settled_assets[asset_name] += volume else: self.settled_cash += price * volume self.available_assets[asset_name] -= volume self.settled_assets[asset_name] -= volume def asset_endowment(self): return self.subsession.config.asset_endowment def cash_endowment(self): return self.subsession.config.cash_endowment def update_holdings_available(self, order, removed): sign = 1 if removed else -1 if not order.is_bid: self.available_assets[ order.exchange.asset_name] += order.volume * sign ## Bayes methods def BU_low(self, k, m): return (math.pow(0.6, k) + math.pow(.4, m)) / ( (math.pow(.6, k) + math.pow(.4, m)) + (math.pow(.4, k) + math.pow(.6, m))) def BU_hi(self, k, m): return (math.pow(0.8, k) + math.pow(.2, m)) / ( (math.pow(.8, k) + math.pow(.2, m)) + (math.pow(.2, k) + math.pow(.8, m))) def BU_env_b(self, l, h): return (((math.pow(0.6, l) * math.pow(.4, 8 - l)) * (math.pow(.8, h) * math.pow(.2, 8 - h))) / (((math.pow(.6, l) * math.pow(.4, 8 - l) * math.pow(.8, h) * math.pow(.2, 8 - h)) + (math.pow(.4, l) * math.pow(.6, 8 - l) * math.pow(.2, h) * math.pow(.8, 8 - h))))) ## defined Variables ranking = models.IntegerField() profit = models.IntegerField() total_payoff = models.IntegerField() payment_signal1 = models.IntegerField() world_state = models.IntegerField() signal1_black = models.IntegerField() signal1_white = models.IntegerField() signal_nature = models.IntegerField() total_black = models.IntegerField() total_white = models.IntegerField() total_black_low = models.IntegerField() total_black_high = models.IntegerField() Question_1_pre_int = models.IntegerField() Question_1_post_int = models.IntegerField() Question_1_payoff_pre = models.IntegerField(initial=0) Question_2_payoff_pre = models.IntegerField(initial=0) Question_3_payoff_pre = models.IntegerField(initial=0) Question_1_payoff_post = models.IntegerField(initial=0) Question_2_payoff_post = models.IntegerField(initial=0) Question_3_payoff_post = models.IntegerField(initial=0) survey_avg_pay = models.IntegerField() profit = models.IntegerField() asset_value = models.IntegerField() payoff_from_trading = models.IntegerField() shares = models.IntegerField() average_payoff = models.IntegerField() ## Questions Pre Question_1_pre = models.StringField(label=''' Your answer:''') Question_1_post = models.StringField(label=''' Your answer:''') Question_2_pre = models.IntegerField(min=100, max=300, label=''' Enter a number between 100 and 300.''') Question_2_post = models.IntegerField(min=100, max=300, label=''' Enter a number between 100 and 300.''') Question_3_pre = models.IntegerField(choices=[1, 2, 3, 4, 5, 6, 7, 8], label=''' Please choose one of the following. ''') Question_3_post = models.IntegerField(choices=[1, 2, 3, 4, 5, 6, 7, 8], label=''' Please choose one of the following. ''') ####################################################################### ### sets the proft for an indivdual player ####################################################################### def set_profit(self): self.shares = self.settled_assets['A'] old_asset_value = 0 if self.world_state == 1: self.asset_value = self.shares * 300 self.profit = self.asset_value + self.settled_cash ## bad state else: self.asset_value = self.shares * 100 self.profit = self.asset_value + self.settled_cash ####################################################################### ### sets the proft for an indivdual player ####################################################################### def get_profit(self): return self.profit ####################################################################### ### calculates payoff ####################################################################### def set_total_payoff(self): ###################question 1 post##################################### p_n_pre = random.randint(0, 99) n_asset_binomail_pre = np.random.binomial(1, p_n_pre / 100) n_asset_value_pre = n_asset_binomail_pre * 200 + 100 ####################################################################### p_n_post = random.randint(0, 99) n_asset_binomail_post = np.random.binomial(1, p_n_post / 100) n_asset_value_post = n_asset_binomail_post * 200 + 100 ################question 1 post######################################### try: self.Question_1_post_int = int(self.Question_1_post) except ValueError: self.Question_1_post_int = -2 if self.Question_1_post_int > 100: self.Question_1_payoff_post = 0 elif self.Question_1_post_int < 0: self.Question_1_payoff_post = 0 elif self.Question_1_post_int > p_n_post: self.Question_1_payoff_post = self.world_state * 200 + 100 else: self.Question_1_payoff_post = n_asset_value_post ################question 1 pre######################################### try: self.Question_1_pre_int = int(self.Question_1_pre) except ValueError: self.Question_1_pre_int = -2 if self.Question_1_pre_int > 100: self.Question_1_payoff_pre = 0 elif self.Question_1_pre_int < 0: self.Question_1_payoff_pre = 0 elif self.Question_1_pre_int > p_n_pre: self.Question_1_payoff_pre = self.world_state * 200 + 100 else: self.Question_1_payoff_pre = n_asset_value_pre ################### ### question 2 post################################### p_n = random.randint(100, 300) if self.Question_2_post > p_n: self.Question_2_payoff_post = self.world_state * 200 + 100 else: self.Question_2_payoff_post = p_n ################### ### question 2 pre################################### p_n = random.randint(100, 300) if self.Question_2_pre > p_n: self.Question_2_payoff_pre = self.world_state * 200 + 100 else: self.Question_2_payoff_pre = p_n ################### ### question 3 pre################################### ##C correct ranking C = self.ranking ##R is the reported belief R = self.Question_3_pre self.Question_3_payoff_pre = (int)(100 - (math.pow((C - R), 2))) ################### ### question 3 post################################### ##C correct ranking C = self.ranking ##R is the reported belief R = self.Question_3_post self.Question_3_payoff_post = (int)(100 - (math.pow((C - R), 2))) ###set to zero if did not answer survye questions######################## if self.Question_1_pre_int == -1: self.Question_1_payoff_pre = 0 if self.Question_1_pre_int == -2: self.Question_1_payoff_pre = 0 if self.Question_1_post_int == -1: self.Question_1_payoff_post = 0 if self.Question_1_post_int == -2: self.Question_1_payoff_post = 0 if self.Question_2_pre == -1: self.Question_2_payoff_pre = 0 if self.Question_2_post == -1: self.Question_2_payoff_post = 0 if self.Question_3_pre == -1: self.Question_3_payoff_pre = 0 if self.Question_3_post == -1: self.Question_3_payoff_post = 0 ## set total payoff ############################### self.payoff_from_trading = self.profit self.survey_avg_pay = (int)( (self.Question_1_payoff_pre + self.Question_2_payoff_pre + self.Question_3_payoff_pre + self.Question_1_payoff_post + self.Question_2_payoff_post + self.Question_3_payoff_post) / 6) self.total_payoff = self.survey_avg_pay + self.payoff_from_trading ## sets payoff to best payoff per round conversion_rate = .0017 if self.subsession.round_number > 2: self.payoff = self.payoff + (self.total_payoff * conversion_rate)
class Edge(models.Model): network = models.ForeignKey(Network) node_from = models.ForeignKey(Node, related_name="node_from") node_to = models.ForeignKey(Node, related_name="node_to")
class GeneralQuestion(djmodels.Model): player = models.ForeignKey(Player, related_name="%(app_label)s_%(class)s_question") class Meta: abstract = True
class Player(BasePlayer): def get_entry_table(self): player_node = self.node P = player_node.network.group_set.first().get_player_by_id(1) messageRound = P.participant.vars['message_round'] posted_wall_messages = Message.objects.filter( messageRound=messageRound) posted_wall_messages = posted_wall_messages.exclude(deleted=True) posted_wall_messages = posted_wall_messages.filter( createdBy=player_node) entryList = posted_wall_messages message_list = player_node.wall_set.first( ).subsession.session.config['messages'].split('/') neighbor_list = list(set(player_node.get_neighbors())) table = {} for n in neighbor_list: table[n.avatar.get_name()] = { 'name': n.avatar.get_name(), 'icon': n.avatar.src, '0': False, '1': False } table[player_node.avatar.get_name()] = { 'name': player_node.avatar.get_name() + ' (you)', 'icon': player_node.avatar.src, '0': False, '1': False } for entry in entryList: name = entry.wall.node.avatar.get_name() table[name]['0'] = ((entry.message == message_list[0]) or table[name]['0']) table[name]['1'] = ((entry.message == message_list[1]) or table[name]['1']) return list(table.values()) def get_private_entry_table(self): player_node = self.node P = player_node.network.group_set.first().get_player_by_id(1) messageRound = P.participant.vars['message_round'] posted_wall_messages = PrivateMessage.objects.filter( messageRound=messageRound) posted_wall_messages = posted_wall_messages.exclude(deleted=True) posted_wall_messages = posted_wall_messages.filter( createdBy=player_node) entryList = posted_wall_messages message_list = player_node.privatemessageboard_set.first( ).subsession.session.config['messages'].split('/') neighbor_list = set(player_node.get_neighbors()) table = {} for n in neighbor_list: table[n.avatar.get_name()] = { 'name': n.avatar.get_name(), 'icon': n.avatar.src, '0': False, '1': False } for entry in entryList: name = entry.wall.node.avatar.get_name() table[name]['0'] = ((entry.message == message_list[0]) or table[name]['0']) table[name]['1'] = ((entry.message == message_list[1]) or table[name]['1']) return list(table.values()) def get_messages(self): wall = self.node.wall_set.first() if self.session.config['instant_messaging'] == 'True': wall_messages = wall.message_set.all() else: p = self.group.get_player_by_id(1) messageRound = p.participant.vars['message_round'] past_wall_messages = wall.message_set.filter( messageRound__lt=messageRound) past_wall_messages = past_wall_messages.exclude(deleted=True) posted_wall_messages = wall.message_set.filter(createdBy=self.node) posted_wall_messages = posted_wall_messages.exclude(deleted=True) wall_messages = past_wall_messages | posted_wall_messages wall_out = [m.to_dict() for m in wall_messages] return wall_out def get_private_messages(self): pmb = self.node.privatemessageboard_set.first() if self.session.config['instant_messaging'] == 'True': private_messages = pmb.privatemessage_set.all() else: p = self.group.get_player_by_id(1) messageRound = p.participant.vars['message_round'] private_messages = pmb.privatemessage_set.filter( messageRound__lt=messageRound) pmb_out = [m.to_dict() for m in private_messages] return pmb_out def get_neighbors(self): results = Edge.objects.filter(node_from=self.node) # neighbors = [Player.objects.get(node=r.node_to) for r in results] neighbors = [r.node_to for r in results] return neighbors def get_avatar(self): return self.avatar.src def get_user_name(self): return self.user_name node = models.ForeignKey(Node, default=1) threshold = models.IntegerField() participate = models.BooleanField(verbose_name="Will you participate?") # Avatar Portions user_name = models.CharField(default='Not Assigned') avatar = models.ForeignKey(Avatar, default=1, related_name='practice_avatar_seq') # Round_Payoff round_payoff = models.CurrencyField() message_cost = models.CurrencyField() continue_practice = models.BooleanField( verbose_name="Would you like to continue with practice rounds?", blank=True, initial=True, choices=[ [True, "Yes, I would like to continue practicing."], [ False, "No, I understand the game and would like to advance to the main rounds." ], ])