Ejemplo n.º 1
0
 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),
     )
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
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()
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
 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')
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
 async def post_receive_json(self, content):
     Session.objects_filter(Session.code.in_(content)).delete()
     await self.send_json('ok')
Ejemplo n.º 8
0
 def session(self):
     return Session.objects_get(id=self._session_pk)