def vars_for_template(self): field_names = otree.export.get_field_names_for_live_update(Participant) display_names = { '_id_in_session': 'Spiller ID', 'code': 'Kode', 'label': 'Label', '_current_page': 'Side', '_current_app_name': 'Spil', '_round_number': 'Runde', '_current_page_name': 'Side navn', 'status': 'Status', '_last_page_timestamp': 'Tid på siden', } callable_fields = {'status', '_id_in_session', '_current_page'} column_names = [display_names[col] for col in field_names] advance_users_button_text = ( "Denne knap fremrykker alle spillere en side." ) participants = self.session.participant_set.filter(visited=True) rows = [] for participant in participants: row = {} for field_name in field_names: value = getattr(participant, field_name) if field_name in callable_fields: value = value() row[field_name] = value rows.append(row) self.context_json = rows page_url_active = {"next_page": "active"} session = self.session room = session.get_room() session_start_urls = [ self.request.build_absolute_uri(participant._start_url()) for participant in session.get_participants() ] app = dict(SessionConfig(self.session.config)) return dict( column_names=column_names, advance_users_button_text=advance_users_button_text, page_url_active=page_url_active, room_wide_url=room.get_room_wide_url(self.request), num_participants=len(session_start_urls), game_name=app )
def initialize_session(self, session_pk, case_number): self.prune() self.participants_by_session[session_pk] = [] session = Session.objects.get(pk=session_pk) if case_number is None: # choose one randomly from otree.session import SessionConfig config = SessionConfig(session.config) num_cases = config.get_num_bot_cases() case_number = random.choice(range(num_cases)) bots = make_bots(session_pk=session_pk, case_number=case_number, use_browser_bots=True) for bot in bots: self.participants_by_session[session_pk].append( bot.participant_code) self.browser_bots[bot.participant_code] = bot
def initialize_session(self, session_pk, case_number): self.prune() self.participants_by_session[session_pk] = [] session = Session.objects.get(pk=session_pk) if case_number is None: # choose one randomly from otree.session import SessionConfig config = SessionConfig(session.config) num_cases = config.get_num_bot_cases() case_number = random.choice(range(num_cases)) bots = make_bots( session_pk=session_pk, case_number=case_number, use_browser_bots=True ) for bot in bots: self.participants_by_session[session_pk].append( bot.participant_code) self.browser_bots[bot.participant_code] = bot
def initialize_session(self, session_pk): self.prune() self.participants_by_session[session_pk] = [] session = Session.objects.get(pk=session_pk) # choose one randomly from otree.session import SessionConfig config = SessionConfig(session.config) num_cases = config.get_num_bot_cases() # choose bot case number randomly...maybe reconsider this? # we can only run one. case_number = random.choice(range(num_cases)) bots = get_bots(session_pk=session_pk, case_number=case_number) for bot in bots: self.participants_by_session[session_pk].append( bot.participant_code) self.browser_bots[bot.participant_code] = bot return {'ok': True}
def handle_file(self, path): new_conf = CustomOtreeConfig.from_yaml(path).get_otree_config() config_obj = SessionConfig(settings.SESSION_CONFIG_DEFAULTS) config_obj.update(new_conf) config_obj.clean() SESSION_CONFIGS_DICT[new_conf['name']] = config_obj
def get_rows_for_wide_csv(): sessions = Session.objects.order_by('id') session_cache = {row.id: row for row in sessions} session_config_fields = set() for session in sessions: for field_name in SessionConfig(session.config).editable_fields(): session_config_fields.add(field_name) session_config_fields = list(session_config_fields) participants = Participant.objects.order_by('id').values() if not participants: # 1 empty row return [[]] session_fields = get_field_names_for_csv(Session) participant_fields = get_field_names_for_csv(Participant) participant_fields.append('payoff_plus_participation_fee') header_row = [ 'participant.{}'.format(fname) for fname in participant_fields ] header_row += ['session.{}'.format(fname) for fname in session_fields] header_row += [ 'session.config.{}'.format(fname) for fname in session_config_fields ] rows = [header_row] for participant in participants: session = session_cache[participant['session_id']] participant[ 'payoff_plus_participation_fee'] = get_payoff_plus_participation_fee( session, participant) row = [ sanitize_for_csv(participant[fname]) for fname in participant_fields ] row += [ sanitize_for_csv(getattr(session, fname)) for fname in session_fields ] row += [ sanitize_for_csv(session.config.get(fname)) for fname in session_config_fields ] rows.append(row) # heuristic to get the most relevant order of apps app_sequences = collections.Counter() for session in sessions: # we loaded the config earlier app_sequence = session.config['app_sequence'] app_sequences[tuple(app_sequence)] += session.num_participants most_common_app_sequence = app_sequences.most_common(1)[0][0] # can't use settings.INSTALLED_OTREE_APPS, because maybe the app # was removed from SESSION_CONFIGS. app_names_with_data = set() for session in sessions: for app_name in session.config['app_sequence']: app_names_with_data.add(app_name) apps_not_in_popular_sequence = [ app for app in app_names_with_data if app not in most_common_app_sequence ] order_of_apps = list( most_common_app_sequence) + apps_not_in_popular_sequence rounds_per_app = OrderedDict() for app_name in order_of_apps: models_module = get_models_module(app_name) agg_dict = models_module.Subsession.objects.all().aggregate( Max('round_number')) highest_round_number = agg_dict['round_number__max'] if highest_round_number is not None: rounds_per_app[app_name] = highest_round_number for app_name in rounds_per_app: for round_number in range(1, rounds_per_app[app_name] + 1): new_rows = get_rows_for_wide_csv_round(app_name, round_number, sessions) for i in range(len(rows)): rows[i].extend(new_rows[i]) return rows
def get_context_data(self, **kwargs): context = super(SessionDescription, self).get_context_data(**kwargs) context['config'] = SessionConfig(self.session.config) return context
def vars_for_template(self): return dict(config=SessionConfig(self.session.config))
def get_rows_for_wide_csv(session_code): if session_code: sessions = [Session.objects_get(code=session_code)] else: sessions = dbq(Session).order_by('id').all() session_fields = get_fields_for_csv(Session) participant_fields = get_fields_for_csv(Participant) session_ids = [session.id for session in sessions] pps = (Participant.objects_filter( Participant.session_id.in_(session_ids)).order_by( Participant.id).all()) session_cache = {row.id: row for row in sessions} session_config_fields = set() for session in sessions: for field_name in SessionConfig(session.config).editable_fields(): session_config_fields.add(field_name) session_config_fields = list(session_config_fields) if not pps: # 1 empty row return [[]] header_row = [f'participant.{fname}' for fname in participant_fields] header_row += [f'session.{fname}' for fname in session_fields] header_row += [ f'session.config.{fname}' for fname in session_config_fields ] rows = [header_row] for pp in pps: session = session_cache[pp.session_id] row = [getattr(pp, fname) for fname in participant_fields] row += [getattr(session, fname) for fname in session_fields] row += [session.config.get(fname) for fname in session_config_fields] rows.append(row) order_of_apps = _get_best_app_order(sessions) rounds_per_app = OrderedDict() for app_name in order_of_apps: try: models_module = get_models_module(app_name) except ModuleNotFoundError: # this should only happen with devserver because on production server, # you would need to resetdb after renaming an app. logger.warning( f'Cannot export data for app {app_name}, which existed when the session was run ' f'but no longer exists.') continue highest_round_number = dbq( func.max(models_module.Subsession.round_number)).scalar() if highest_round_number is not None: rounds_per_app[app_name] = highest_round_number for app_name in rounds_per_app: for round_number in range(1, rounds_per_app[app_name] + 1): new_rows = get_rows_for_wide_csv_round(app_name, round_number, sessions) for i in range(len(rows)): rows[i].extend(new_rows[i]) return [[sanitize_for_csv(v) for v in row] for row in rows]
def get_context_data(self, **kwargs): context = super(SessionDescription, self).get_context_data(**kwargs) config_obj = SessionConfig(self.session.config) context.update(config_obj.get_info()) return context
def get_rows_for_wide_csv(): sessions = Session.objects.order_by('id').annotate( num_participants=Count('participant')).values() session_cache = {row['id']: row for row in sessions} session_config_fields = set() for row in sessions: config = json_loads(row['config']) config = SessionConfig(config) for field_name in config.editable_fields(): session_config_fields.add(field_name) # store it for later, when we need app_sequence row['config'] = config session_config_fields = list(session_config_fields) participants = Participant.objects.order_by('id').values() if not participants: # 1 empty row return [[]] payoff_cache = get_payoff_cache() payoff_plus_participation_fee_cache = get_payoff_plus_participation_fee_cache(payoff_cache) session_fields = get_field_names_for_csv(Session) participant_fields = get_field_names_for_csv(Participant) participant_fields += ['payoff', 'payoff_plus_participation_fee'] header_row = ['participant.{}'.format(fname) for fname in participant_fields] header_row += ['session.{}'.format(fname) for fname in session_fields] header_row += ['session.config.{}'.format(fname) for fname in session_config_fields] rows = [header_row] for participant in participants: participant['payoff'] = payoff_cache[participant['id']] participant['payoff_plus_participation_fee'] = payoff_plus_participation_fee_cache[participant['id']] row = [sanitize_for_csv(participant[fname]) for fname in participant_fields] session = session_cache[participant['session_id']] row += [sanitize_for_csv(session[fname]) for fname in session_fields] config = session['config'] row += [sanitize_for_csv(config.get(fname)) for fname in session_config_fields] rows.append(row) # heuristic to get the most relevant order of apps app_sequences = collections.Counter() for session in sessions: # we loaded the config earlier app_sequence = session['config']['app_sequence'] app_sequences[tuple(app_sequence)] += session['num_participants'] most_common_app_sequence = app_sequences.most_common(1)[0][0] apps_not_in_popular_sequence = [ app for app in settings.INSTALLED_OTREE_APPS if app not in most_common_app_sequence] order_of_apps = list(most_common_app_sequence) + apps_not_in_popular_sequence rounds_per_app = OrderedDict() for app_name in order_of_apps: models_module = get_models_module(app_name) agg_dict = models_module.Subsession.objects.all().aggregate(Max('round_number')) highest_round_number = agg_dict['round_number__max'] if highest_round_number is not None: rounds_per_app[app_name] = highest_round_number for app_name in rounds_per_app: for round_number in range(1, rounds_per_app[app_name] + 1): new_rows = get_rows_for_wide_csv_round(app_name, round_number, sessions) for i in range(len(rows)): rows[i].extend(new_rows[i]) return rows
def get_rows_for_wide_csv(): sessions = Session.objects.order_by('id').annotate( num_participants=Count('participant')).values() session_cache = {row['id']: row for row in sessions} session_config_fields = set() for row in sessions: config = json_loads(row['config']) config = SessionConfig(config) for field_name in config.editable_fields(): session_config_fields.add(field_name) # store it for later, when we need app_sequence row['config'] = config session_config_fields = list(session_config_fields) participants = Participant.objects.order_by('id').values() if not participants: # 1 empty row return [[]] payoff_cache = get_payoff_cache() payoff_plus_participation_fee_cache = get_payoff_plus_participation_fee_cache( payoff_cache) session_fields = get_field_names_for_csv(Session) participant_fields = get_field_names_for_csv(Participant) participant_fields += ['payoff', 'payoff_plus_participation_fee'] header_row = [ 'participant.{}'.format(fname) for fname in participant_fields ] header_row += ['session.{}'.format(fname) for fname in session_fields] header_row += [ 'session.config.{}'.format(fname) for fname in session_config_fields ] rows = [header_row] for participant in participants: participant['payoff'] = payoff_cache[participant['id']] participant[ 'payoff_plus_participation_fee'] = payoff_plus_participation_fee_cache[ participant['id']] row = [ sanitize_for_csv(participant[fname]) for fname in participant_fields ] session = session_cache[participant['session_id']] row += [sanitize_for_csv(session[fname]) for fname in session_fields] config = session['config'] row += [ sanitize_for_csv(config.get(fname)) for fname in session_config_fields ] rows.append(row) # heuristic to get the most relevant order of apps app_sequences = collections.Counter() for session in sessions: # we loaded the config earlier app_sequence = session['config']['app_sequence'] app_sequences[tuple(app_sequence)] += session['num_participants'] most_common_app_sequence = app_sequences.most_common(1)[0][0] apps_not_in_popular_sequence = [ app for app in settings.INSTALLED_OTREE_APPS if app not in most_common_app_sequence ] order_of_apps = list( most_common_app_sequence) + apps_not_in_popular_sequence rounds_per_app = OrderedDict() for app_name in order_of_apps: models_module = get_models_module(app_name) agg_dict = models_module.Subsession.objects.all().aggregate( Max('round_number')) highest_round_number = agg_dict['round_number__max'] if highest_round_number is not None: rounds_per_app[app_name] = highest_round_number for app_name in rounds_per_app: for round_number in range(1, rounds_per_app[app_name] + 1): new_rows = get_rows_for_wide_csv_round(app_name, round_number, sessions) for i in range(len(rows)): rows[i].extend(new_rows[i]) return rows
def get_rows_for_wide_csv(session_code): if session_code: sessions = [Session.objects.get(code=session_code)] else: sessions = Session.objects.order_by('id') participants = ( Participant.objects.filter(session__in=sessions).order_by('id').values() ) session_cache = {row.id: row for row in sessions} session_config_fields = set() for session in sessions: for field_name in SessionConfig(session.config).editable_fields(): session_config_fields.add(field_name) session_config_fields = list(session_config_fields) if not participants: # 1 empty row return [[]] session_fields = get_field_names_for_csv(Session) participant_fields = get_field_names_for_csv(Participant) participant_fields.append('payoff_plus_participation_fee') header_row = ['participant.{}'.format(fname) for fname in participant_fields] header_row += ['session.{}'.format(fname) for fname in session_fields] header_row += ['session.config.{}'.format(fname) for fname in session_config_fields] rows = [header_row] for participant in participants: session = session_cache[participant['session_id']] participant[ 'payoff_plus_participation_fee' ] = get_payoff_plus_participation_fee(session, participant) row = [sanitize_for_csv(participant[fname]) for fname in participant_fields] row += [sanitize_for_csv(getattr(session, fname)) for fname in session_fields] row += [ sanitize_for_csv(session.config.get(fname)) for fname in session_config_fields ] rows.append(row) # heuristic to get the most relevant order of apps app_sequences = collections.Counter() for session in sessions: # we loaded the config earlier app_sequence = session.config['app_sequence'] app_sequences[tuple(app_sequence)] += session.num_participants most_common_app_sequence = app_sequences.most_common(1)[0][0] # can't use settings.INSTALLED_OTREE_APPS, because maybe the app # was removed from SESSION_CONFIGS. app_names_with_data = set() for session in sessions: for app_name in session.config['app_sequence']: app_names_with_data.add(app_name) apps_not_in_popular_sequence = [ app for app in app_names_with_data if app not in most_common_app_sequence ] order_of_apps = list(most_common_app_sequence) + apps_not_in_popular_sequence rounds_per_app = OrderedDict() for app_name in order_of_apps: try: models_module = get_models_module(app_name) except ModuleNotFoundError: # this should only happen with devserver because on production server, # you would need to resetdb after renaming an app. logger.warning( f'Cannot export data for app {app_name}, which existed when the session was run ' f'but no longer exists.' ) continue agg_dict = models_module.Subsession.objects.all().aggregate(Max('round_number')) highest_round_number = agg_dict['round_number__max'] if highest_round_number is not None: rounds_per_app[app_name] = highest_round_number for app_name in rounds_per_app: for round_number in range(1, rounds_per_app[app_name] + 1): new_rows = get_rows_for_wide_csv_round(app_name, round_number, sessions) for i in range(len(rows)): rows[i].extend(new_rows[i]) return rows