示例#1
0
 def set_players(self, players_list):
     Constants = self._Constants
     roles = get_roles(Constants)
     for i, player in enumerate(players_list, start=1):
         player.group = self
         player.id_in_group = i
         player._role = get_role(roles, i)
     db.commit()
示例#2
0
 def get_player_by_role(self, role):
     if get_roles(self._Constants):
         try:
             return self.player_set.get(_role=role)
         except django.core.exceptions.ObjectDoesNotExist:
             pass
     else:
         for p in self.get_players():
             if p.role() == role:
                 return p
     msg = f'No player with role "{role}"'
     raise ValueError(msg)
示例#3
0
 def get_player_by_role(self, role):
     if get_roles(self._Constants):
         try:
             return self.player_set.filter_by(_role=role).one()
         except NoResultFound:
             pass
     else:
         for p in self.get_players():
             if p.role() == role:
                 return p
     msg = f'No player with role "{role}"'
     raise ValueError(msg)
示例#4
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