from otree.api import * from otree.models import subsession, player import pandas as pd import pickle # import random # import pickle doc = """ Mini-Twitter """ class C(BaseConstants): NAME_IN_URL = 'connectionserver' PLAYERS_PER_GROUP = None NUM_ROUNDS = 3 CSV = pd.read_csv('CSV.csv') texto_share = "Would you like to share this opinion with your connections?" no_share = "Nothing to share." txt_importTU = "How important is this issue to YOU?" txt_importTO = "How important do you think this issue is to your CONNECTIONS?" # Q = random.randint(0, 3) #### endowment = 100 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): name = models.StringField() nickname = models.StringField() opinion = models.StringField() preg = models.IntegerField() connections = models.IntegerField() reply = models.StringField( choices=[['Yes', 'Yes'], ['No', 'No'], ['No_Answer', 'Prefer not to answer']], label=" " ) shareAnswer = models.BooleanField( choices=[[True, 'Yes'], [False, 'No']], label=C.texto_share ) importantTU = models.IntegerField( choices=[[0, 'Not important at all'], [1, 'Slightly important'], [2, 'Moderately important'], [3, 'Important'], [4, 'Very important']], label=C.txt_importTU ) importantTO = models.IntegerField( choices=[[0, 'Not important at all'], [1, 'Slightly important'], [2, 'Moderately important'], [3, 'Important'], [4, 'Very important']], label=C.txt_importTO ) class Subscription(ExtraModel): # we store the player objects and id_in_group redundantly, # for convenience and performance leader = models.Link(Player) leader_id_in_group = models.IntegerField() follower = models.Link(Player) follower_id_in_group = models.IntegerField() class Connection(ExtraModel): # we store the player objects and id_in_group redundantly, # for convenience and performance target = models.Link(Player) target_id_in_group = models.IntegerField() source = models.Link(Player) source_id_in_group = models.IntegerField() class Message(ExtraModel): player = models.Link(Player) player_id_in_group = models.IntegerField() group = models.Link(Group) text = models.LongStringField() def to_dict(msg: Message): return dict(id_in_group=msg.player_id_in_group, text=msg.text) """ def player_opinion(player: Player): if player.shareAnswer: if player.reply == 'Yes': opinion = 'By law, abortion should NEVER be permitted.' elif player.reply == 'No': opinion = 'Abortion should NOT be banned by law.' else: opinion = 'I don\'t know whether abortion should or should not be banned by law.' else: opinion = C.no_share return opinion """ def player_opinion(player: Player): N = player.round_number - 1 if player.reply == 'Yes': opinion = C.CSV['ShareYesAgree'][N] elif player.reply == 'No': opinion = C.CSV['ShareYesDonotAgree'][N] else: opinion = C.CSV['ShareYesDonotKnow'][N] return opinion def get_follower_ids(player: Player, including_myself): ids = [sub.follower_id_in_group for sub in Subscription.filter(leader=player)] if including_myself: ids.append(player.id_in_group) return ids def get_connections_ids(player: Player, including_myself): aux = [sub.source_id_in_group for sub in Connection.filter(target=player)] ids = [sub.target_id_in_group for sub in Connection.filter(source=player)] ids = ids + aux if including_myself: ids.append(player.id_in_group) return ids def live_method(player: Player, data): round = player.round_number opinion = player_opinion(player) group = player.group my_id = player.id_in_group msg_type = data['type'] if data['type'] == 'write': msg = Message.create(player=player, player_id_in_group=my_id, text=opinion, # text=data['text'], group=group, ) connections = get_connections_ids(player, including_myself=True) return {connection: dict(messages=[to_dict(msg)]) for connection in connections} broadcast = {} if msg_type == 'toggle_follow': leader_id = data['id_in_group'] leader = group.get_player_by_id(leader_id) subs = Subscription.filter(follower=player, leader=leader) if subs: [sub] = subs sub.delete() else: Subscription.create( leader=leader, leader_id_in_group=leader.id_in_group, follower=player, follower_id_in_group=my_id, ) # notify the other person of the change to their followers followers = get_follower_ids(leader, including_myself=True) i_dont_follow = [p.id_in_group for p in group.get_players() if p.id_in_group not in followers] broadcast[leader_id] = dict(followers=followers, i_dont_follow=i_dont_follow) if msg_type == 'accept': accept_id = data['id_in_group'] accept = group.get_player_by_id(accept_id) subs = Subscription.filter(follower=accept, leader=player) if subs: [sub] = subs sub.delete() Connection.create( target=player, target_id_in_group=my_id, source=accept, source_id_in_group=accept.id_in_group, ) # notify the other person of the change to their followers followers = get_follower_ids(accept, including_myself=True) i_follow = [sub.leader_id_in_group for sub in Subscription.filter(follower=accept)] connections = get_connections_ids(accept, including_myself=True) i_dont_follow = [p.id_in_group for p in group.get_players() if p.id_in_group not in followers + connections + i_follow] # UPDATE FEED unfiltered_messages_accept = Message.filter(group=group) my_feed_authors = connections + [accept_id] messages = [to_dict(m) for m in unfiltered_messages_accept if m.player_id_in_group in my_feed_authors] broadcast[accept_id] = dict(followers=followers, i_follow=i_follow, i_dont_follow=i_dont_follow, my_connections=connections, messages=messages, full_load=True) if msg_type == 'reject': reject_id = data['id_in_group'] reject = group.get_player_by_id(reject_id) subs = Subscription.filter(follower=reject, leader=player) if subs: [sub] = subs sub.delete() followers = get_follower_ids(reject, including_myself=True) i_follow = [sub.leader_id_in_group for sub in Subscription.filter(follower=reject)] i_dont_follow = [p.id_in_group for p in group.get_players() if p.id_in_group not in followers + i_follow] broadcast[reject_id] = dict(followers=followers, i_follow=i_follow, i_dont_follow=i_dont_follow) if msg_type == 'disconnect': disconnect_id = data['id_in_group'] disconnect = group.get_player_by_id(disconnect_id) cons = Connection.filter(target=disconnect, source=player) if cons: [con] = cons con.delete() auxs = Connection.filter(target=player, source=disconnect) if auxs: [aux] = auxs aux.delete() # notify the other person of the change to their followers followers = get_follower_ids(disconnect, including_myself=True) i_follow = [sub.leader_id_in_group for sub in Subscription.filter(follower=disconnect)] connections = get_connections_ids(disconnect, including_myself=True) i_dont_follow = [p.id_in_group for p in group.get_players() if p.id_in_group not in followers + connections + i_follow] broadcast[disconnect_id] = dict(followers=followers, i_follow=i_follow, i_dont_follow=i_dont_follow, my_connections=connections) else: connections = get_connections_ids(player, including_myself=True) followers = get_follower_ids(player, including_myself=True) i_follow = [sub.leader_id_in_group for sub in Subscription.filter(follower=player)] i_dont_follow = [p.id_in_group for p in group.get_players() if p.id_in_group not in followers + i_follow + connections] unfiltered_messages = Message.filter(group=group) my_feed_authors = connections + [my_id] messages = [to_dict(m) for m in unfiltered_messages if m.player_id_in_group in my_feed_authors] # connections # connections = get_connections_ids(player, including_myself=True) player.participant.connections = connections # followers # followers = get_follower_ids(player, including_myself=True) player.participant.followers = followers # i_follow # i_follow = [sub.leader_id_in_group for sub in Subscription.filter(follower=player)] player.participant.i_follow = i_follow # i_dont_follow # i_dont_follow = [p.id_in_group for p in group.get_players() if p.id_in_group not in followers + i_follow + connections] player.participant.i_dont_follow = i_dont_follow # messages # unfiltered_messages = Message.filter(group=group) # i see my own messages in my feed # my_feed_authors = connections + [my_id] # messages = [to_dict(m) for m in unfiltered_messages if m.player_id_in_group in my_feed_authors] player.participant.messages = messages """ player.participant.connections = connections player.participant.followers = followers player.participant.i_follow = i_follow player.participant.i_dont_follow = i_dont_follow player.participant.my_feed_authors = my_feed_authors player.participant.messages = messages """ broadcast.update( { my_id: dict( full_load=True, followers=followers, i_follow=i_follow, i_dont_follow=i_dont_follow, my_connections=connections, messages=messages, ) } ) with open("test.pickle", "wb") as file: pickle.dump(broadcast, file, pickle.HIGHEST_PROTOCOL) return broadcast # PAGES class Questionnaire(Page): form_model = 'player' form_fields = ['reply', 'importantTU', 'importantTO'] @staticmethod def vars_for_template(player: Player): N = player.round_number - 1 return { 'my_label': C.CSV['label'][N] } @staticmethod def before_next_page(player: Player, timeout_happened): player.opinion = player_opinion(player) player.participant.opinion = player.opinion player.nickname = player.participant.name + " " + "(" + "participant " + str(player.id_in_group) + ")" class PageOne(Page): form_model = 'player' form_fields = ['shareAnswer'] @staticmethod def vars_for_template(player: Player): group = player.group my_id = player.id_in_group name = player.participant.name opinion = player_opinion(player) return {'opinion': opinion, 'my_id': my_id, 'name': name, 'nickname': player.nickname} @staticmethod def before_next_page(player: Player, timeout_happened): if not player.shareAnswer: player.opinion = C.no_share player.participant.opinion = player.opinion class MyPage(Page): live_method = live_method @staticmethod def vars_for_template(player: Player): group = player.group my_id = player.id_in_group opinion = player_opinion(player) return {'opinion': opinion, 'my_id': my_id, 'group': group, 'connections': live_method} @staticmethod def js_vars(player: Player): opinion = player_opinion(player) return dict(my_id=player.id_in_group, my_name=player.participant.name) class MyWaitPage(WaitPage): @staticmethod def after_all_players_arrive(group: Group): for player in group.get_players(): player.participant.round = 10 page_sequence = [Questionnaire, PageOne, MyPage, MyWaitPage] # page_sequence = [IntroPage, Questionnaire, PageOne, MyPage]