def vars_for_template(self): is_archive = bool(self.request.query_params.get('archived')) sessions = (Session.objects_filter(is_demo=False, archived=is_archive).order_by( Session.id.desc()).all()) return dict( is_archive=is_archive, sessions=sessions, archived_sessions_exist=Session.objects_exists(archived=True), )
def get(self, request): admin_secret_code = request.path_params['admin_secret_code'] if admin_secret_code != otree.common.get_admin_secret_code(): return Response('Incorrect code', status_code=404) session_code = GlobalState.browser_bots_launcher_session_code if session_code: try: session = Session.objects_get(code=session_code) except NoResultFound: # maybe it's an old session pass else: participant = (session.pp_set.filter_by( visited=False).order_by('id').first()) if not participant: return no_participants_left_http_response() # 2014-10-17: needs to be here even if it's also set in # the next view to prevent race conditions participant.visited = True return RedirectResponse(participant._start_url(), status_code=302) ctx = dict( view=self, title_text='Please wait', body_text='Waiting for browser bots session to begin', ) return render("otree/WaitPage.html", ctx)
def run_bots(session_id, case_number=None): session = Session.objects_get(id=session_id) bot_list = make_bots(session_pk=session.id, case_number=case_number, use_browser_bots=False) if session.get_room() is None: session.mock_exogenous_data() runner = SessionBotRunner(bots=bot_list) runner.play()
def make_bots(*, session_pk, case_number, use_browser_bots) -> List[ParticipantBot]: update_kwargs = {Participant._is_bot: True} if use_browser_bots: update_kwargs[Participant.is_browser_bot] = True Participant.objects_filter(session_id=session_pk).update(update_kwargs) bots = [] # can't use .distinct('player_pk') because it only works on Postgres # this implicitly orders by round also session = Session.objects_get(id=session_pk) participant_codes = values_flat(session.pp_set.order_by('id'), Participant.code) player_bots_dict = {pcode: [] for pcode in participant_codes} for app_name in session.config['app_sequence']: bots_module = get_bots_module(app_name) models_module = get_models_module(app_name) Player = models_module.Player players = (Player.objects_filter(session_id=session_pk).join( Participant).order_by('round_number').with_entities( Player.id, Participant.code, Player.subsession_id)) for player_id, participant_code, subsession_id in players: player_bot = bots_module.PlayerBot( case_number=case_number, app_name=app_name, player_pk=player_id, subsession_pk=subsession_id, participant_code=participant_code, session_pk=session_pk, ) player_bots_dict[participant_code].append(player_bot) executed_live_methods = set() for participant_code, player_bots in player_bots_dict.items(): bot = ParticipantBot( participant_code, player_bots=player_bots, executed_live_methods=executed_live_methods, ) bots.append(bot) return bots
async def post(self, request): post_data = self.get_post_data() code_list = post_data.getlist('session') for session in Session.objects_filter(Session.code.in_(code_list)): session.archived = not session.archived return self.redirect('Sessions')
def create_session( session_config_name, *, num_participants, label='', room_name=None, is_mturk=False, is_demo=False, modified_session_config_fields=None, ) -> Session: num_subsessions = 0 try: session_config = SESSION_CONFIGS_DICT[session_config_name] except KeyError: msg = 'Session config "{}" not found in settings.SESSION_CONFIGS.' raise KeyError(msg.format(session_config_name)) from None else: # copy so that we don't mutate the original # .copy() returns a dict, so need to convert back to SessionConfig session_config = SessionConfig(session_config.copy()) modified_config = modified_session_config_fields or {} # this is for API. don't want to mislead people # to put stuff in the session config that should be in the session. bad_keys = modified_config.keys() & NON_EDITABLE_FIELDS if bad_keys: raise Exception( f'The following session config fields are not editable: {bad_keys}' ) session_config.update(modified_config) # check validity and converts serialized decimal & currency values # back to their original data type (because they were serialized # when passed through channels session_config.clean() # check that it divides evenly session_lcm = session_config.get_lcm() if num_participants is None: # most games are multiplayer, so if it's under 2, we bump it to 2 num_participants = max(session_lcm, 2) else: if num_participants % session_lcm: msg = ( 'Session Config {}: Number of participants ({}) is not a multiple ' 'of group size ({})' ).format(session_config['name'], num_participants, session_lcm) raise ValueError(msg) session = Session( config=session_config, label=label, is_demo=is_demo, num_participants=num_participants, is_mturk=is_mturk, ) db.add(session) db.commit() session_code = session.code participants = [ Participant( id_in_session=id_in_session, session=session, _session_code=session_code, ) for id_in_session in list(range(1, num_participants + 1)) ] db.add_all(participants) db.commit() # participant_values = ( # db.query(Participant) # .filter(Session.id == session.id) # .order_by('id') # .with_entities(Participant.id, Participant.code) # ).all() participant_values = ( db.query(Participant) .join(Session) .filter(Session.id == session.id) .order_by(Participant.id) .with_entities(Participant.id, Participant.code) ).all() num_pages = 0 for app_name in session_config['app_sequence']: views_module = common.get_pages_module(app_name) models_module = get_models_module(app_name) Constants: BaseConstants = models_module.Constants num_subsessions += Constants.num_rounds round_numbers = list(range(1, Constants.num_rounds + 1)) num_pages += Constants.num_rounds * len(views_module.page_sequence) Subsession = models_module.Subsession Group = models_module.Group Player = models_module.Player subsessions = [ Subsession(round_number=round_number, session=session) for round_number in round_numbers ] db.add_all(subsessions) db.commit() subsessions = ( dbq(Subsession) .filter_by(session=session) .order_by('round_number') .with_entities('id', 'round_number') ) ppg = Constants.players_per_group if ppg is None or Subsession._has_group_by_arrival_time(): ppg = num_participants num_groups_per_round = int(num_participants / ppg) groups_to_create = [] for ss_id, ss_rd in subsessions: for id_in_subsession in range(1, num_groups_per_round + 1): groups_to_create.append( Group( session=session, subsession_id=ss_id, round_number=ss_rd, id_in_subsession=id_in_subsession, ) ) db.add_all(groups_to_create) groups = ( dbq(Group).filter_by(session=session).order_by('id_in_subsession') ).all() groups_lookup = defaultdict(list) for group in groups: groups_lookup[group.subsession_id].append(group.id) players_to_create = [] for ss_id, ss_rd in subsessions: roles = get_roles(Constants) participant_index = 0 for group_id in groups_lookup[ss_id]: for id_in_group in range(1, ppg + 1): participant = participant_values[participant_index] players_to_create.append( Player( session=session, subsession_id=ss_id, round_number=ss_rd, participant_id=participant[0], group_id=group_id, id_in_group=id_in_group, _role=get_role(roles, id_in_group), ) ) participant_index += 1 # Create players db.add_all(players_to_create) dbq(Participant).filter_by(session=session).update( {Participant._max_page_index: num_pages} ) # make creating_session use the current session, # so that session.save() below doesn't overwrite everything # set earlier for subsession in session.get_subsessions(): subsession.creating_session() # 2017-09-27: moving this inside the transaction session._set_admin_report_app_names() if room_name is not None: from otree.room import ROOM_DICT room = ROOM_DICT[room_name] room.set_session(session) db.commit() return session
async def post_receive_json(self, content): Session.objects_filter(Session.code.in_(content)).delete() await self.send_json('ok')
def session(self): return Session.objects_get(id=self._session_pk)