Exemple #1
0
    def _draft_loop(self) -> None:
        while not self._terminating.is_set():
            try:
                booster = self._booster_queue.get(timeout=2)
            except Empty:
                continue

            self._current_booster = booster

            self.send_message('booster',
                              booster=RawStrategy.serialize(
                                  self._current_booster))

            while not self._terminating.is_set():
                try:
                    pick = self._pick_queue.get(timeout=2)
                except Empty:
                    continue

                if not self.perform_pick(pick):
                    self.send_error(
                        'invalid_pick',
                        pick=pick.serialize(),
                    )
                    continue

                self._pick_counter += 1

                self.send_message(
                    'pick',
                    pick=pick.serialize(),
                    booster=RawStrategy.serialize(self._current_booster),
                    pick_number=self._pick_counter,
                )

                DraftPick.objects.create(
                    seat=self._draft_seat,
                    pack_number=self._draft.pack_counter,
                    pick_number=self._current_booster.pick_number,
                    global_pick_number=self._pick_counter - 1,
                    pack=self._current_booster,
                    pick=pick,
                )

                self._current_booster.pick_number += 1

                if self._current_booster.cubeables:
                    self.passing_to.give_booster(self._current_booster)
                else:
                    self._draft.booster_empty(self._current_booster)
                self._current_booster = None
                self._draft.broadcast_message(
                    'booster_amount_update',
                    drafter=self._drafter.user.pk,
                    queue_size=self.booster_amount,
                )
                break
Exemple #2
0
 def verbose_patch(
         self, patch: t.Union[PatchModel, int, str]) -> VerboseCubePatch:
     return RawStrategy(self._db).deserialize(
         VerboseCubePatch,
         self._make_request('patches/{}/verbose'.format(
             patch.id if isinstance(patch, PatchModel) else patch)),
     )
Exemple #3
0
 def update_content(self, options: t.Mapping[str, t.Any],
                    enabled: bool) -> None:
     self.setText(', '.join(
         sorted(c.name for c in RawStrategy(Context.db).deserialize(
             Infinites,
             options['infinites'],
         ))))
Exemple #4
0
 def update_content(self, options: t.Mapping[str, t.Any],
                    enabled: bool) -> None:
     self._summary.update_content(options, enabled)
     self._infinites = RawStrategy(Context.db).deserialize(
         Infinites, options['infinites'])
     self._table.update_content(self._infinites, enabled)
     self._add_button.setEnabled(enabled)
Exemple #5
0
    def validate(self, value: t.Any) -> t.Mapping[str, t.Any]:
        try:
            RawStrategy(db).deserialize(CardboardSet, value)
        except Exception:
            raise OptionsValidationError('Invalid cardboard set')

        return value
Exemple #6
0
 def to_representation(self, value):
     if self.context.get('request') and strtobool(
             self.context['request'].query_params.get('native', '0')):
         if isinstance(value, Cardboard):
             return value.name
         if isinstance(value, Printing):
             return value.id
         return RawStrategy.serialize(value)
     return self._model_serializer.serialize(value)
Exemple #7
0
 def load(cls, state: t.Any) -> PoolModel:
     state = pickle.loads(state)
     return cls(
         maindeck=state['maindeck'],
         sideboard=state['sideboard'],
         pool=state['pool'],
         infinites=RawStrategy(Context.db).deserialize(
             Infinites, state['infinites']),
     )
Exemple #8
0
 def _deserialize_distribution_possibility(
         self, remote: t.Any) -> DistributionPossibility:
     return DistributionPossibility(
         model_id=remote['id'],
         created_at=remote['created_at'],
         pdf_url=remote['pdf_url'],
         fitness=remote['fitness'],
         trap_collection=RawStrategy(self._db).deserialize(
             TrapCollection, remote['trap_collection']),
         client=self,
     )
Exemple #9
0
 def __reduce__(self):
     return (self._inflate, (
         self.__class__,
         self.cubeable.id if isinstance(self.cubeable, Printing) else
         RawStrategy.serialize(self.cubeable),
         type(self.cubeable),
         self.node_parent,
         self.values,
         self._release_id,
         self._get_additional_reduce(),
     ))
Exemple #10
0
    def _finished_callback_wrapper(self, draft: Draft):
        self._finished_callback()

        tournament_type, tournament_config, match_type = TournamentOptions.deserialize_options(
            self.tournament_options)

        session = LimitedSession.objects.create(
            game_type='draft',
            format=self.format,
            open_decks=self.open_decks,
            open_pools=self.open_pools,
            pool_specification=self._pool_specification,
            infinites=RawStrategy(db).deserialize(Infinites, self.infinites),
            allow_cheating=self.allow_cheating,
            tournament_type=tournament_type,
            tournament_config=tournament_config,
            match_type=match_type,
        )

        draft.draft_session.limited_session = session
        draft.draft_session.save(update_fields=('limited_session', ))

        if self.reverse:
            drafters = list(draft.interfaces.items())
            random.shuffle(drafters)
            for ((drafter, interface),
                 (_, next_interface)) in zip(drafters,
                                             drafters[1:] + [drafters[0]]):
                pool = Pool.objects.create(
                    user=drafter.user,
                    session=session,
                    pool=next_interface.pool,
                )
                interface.send_message(
                    'completed',
                    pool_id=pool.id,
                    session_name=session.name,
                )
        else:
            for drafter, interface in draft.interfaces.items():
                pool = Pool.objects.create(
                    user=drafter.user,
                    session=session,
                    pool=interface.pool,
                )
                interface.send_message(
                    'completed',
                    pool_id=pool.id,
                    session_name=session.name,
                )
Exemple #11
0
    def _handle_add(self) -> None:
        cardboard, accepted = SelectCardboardDialog.get_cardboard()

        if not accepted:
            return

        self._lobby_view.lobby_model.set_options(
            self._lobby_view.lobby.name,
            {
                'infinites':
                RawStrategy.serialize(self._infinites +
                                      Infinites((cardboard, ))),
            },
        )
Exemple #12
0
    def keyPressEvent(self, key_event: QtGui.QKeyEvent):
        pressed_key = key_event.key()

        if pressed_key == QtCore.Qt.Key_Delete and self._enabled:
            item = self.currentItem()
            if item is not None:
                self._lobby_view.lobby_model.set_options(
                    self._lobby_view.lobby.name,
                    {
                        'infinites':
                        RawStrategy.serialize(self._infinites - Infinites(
                            (Context.db.cardboards[item.data(0)], ))),
                    },
                )
        else:
            super().keyPressEvent(key_event)
Exemple #13
0
 def serialize(self) -> t.Mapping[str, t.Any]:
     return {
         'drafters': [
             UserSerializer(drafter.user).data
             for drafter in self._drafters.all
         ],
         'pack_amount':
         self._pack_amount,
         'draft_format':
         self._draft_format,
         'pool_specification':
         PoolSpecificationSerializer(self._pool_specification).data,
         'infinites':
         RawStrategy.serialize(self._infinites),
         'reverse':
         self._reverse,
     }
Exemple #14
0
    def _on_booster_specification_value_change(self, option: str,
                                               value: t.Any) -> None:
        current_options = copy.copy(
            self._lobby_view.lobby.game_options['pool_specification'])
        current_options[self._current_specification_index][option] = value

        if len(current_options) == 1 and current_options[0][
                'type'] == CubeBoosterSpecification.__name__ and option == 'release':
            Context.cube_api_client.release(value).then(
                lambda release: self._lobby_view.lobby_model.set_options(
                    self._lobby_view.lobby.name,
                    {'infinites': RawStrategy.serialize(release.infinites)},
                ))

        self._lobby_view.lobby_model.set_options(
            self._lobby_view.lobby.name,
            {'pool_specification': current_options},
        )
Exemple #15
0
    def __init__(
        self,
        host: str,
        db: CardDatabase,
        *,
        scheme: str = 'https',
        token: t.Optional[str] = None,
        verify_ssl: bool = True,
    ):
        super().__init__(host,
                         db,
                         token=token,
                         scheme=scheme,
                         verify_ssl=verify_ssl)

        self._strategy = RawStrategy(db)

        self._versioned_cubes = None
Exemple #16
0
    def receive_message(self, message: t.Any) -> None:
        message_type = message.get('type')

        if message_type == 'pick':
            pick = message.get('pick')
            if pick is None:
                self.send_error('empty_pick')
                return

            try:
                pick = RawStrategy(db).deserialize(self.pick_type, pick)
            except SerializationException:
                self.send_error('misconstrued_pick')
                return

            self._pick_queue.put(pick)

        else:
            self.send_error('unknown_message_type', message_type=message_type)
Exemple #17
0
 def _inflate(
     card_type: t.Type[PhysicalCard],
     cubeable: t.Any,
     cubeable_type: t.Optional[t.Type],
     node_parent: t.Optional[PhysicalCard],
     values: t.MutableMapping[str, t.Any],
     release_id: t.Optional[int],
     additional_values: t.Optional[t.Dict[str, t.Any]],
 ) -> PhysicalCard:
     card = card_type(
         (Context.db.printings[cubeable] if isinstance(cubeable, int) else
          RawStrategy(Context.db).deserialize(cubeable_type, cubeable)),
         node_parent,
         values,
         release_id=release_id,
     )
     if additional_values:
         card.__dict__.update(additional_values)
     return card
Exemple #18
0
    def __init__(
        self,
        options: t.Mapping[str, t.Any],
        players: t.AbstractSet[AbstractUser],
        callback: t.Callable[[], None],
    ):
        super().__init__(options, players, callback)

        tournament_type, tournament_config, match_type = TournamentOptions.deserialize_options(
            self.tournament_options)

        with transaction.atomic():
            pool_specification = PoolSpecification.from_options(
                self.pool_specification)
            session = LimitedSession.objects.create(
                game_type='sealed',
                format=self.format,
                open_decks=self.open_decks,
                open_pools=self.open_pools,
                pool_specification=pool_specification,
                infinites=RawStrategy(db).deserialize(Infinites,
                                                      self.infinites),
                tournament_type=tournament_type,
                tournament_config=tournament_config,
                match_type=match_type,
            )

            self._keys = {}

            try:
                for player, pool in zip(
                        players,
                        itertools.repeat(pool_specification.get_pool())
                        if self.mirrored else pool_specification.get_pools(
                            len(players))):
                    self._keys[player] = Pool.objects.create(
                        user=player,
                        session=session,
                        pool=pool,
                    ).id
            except GenerateBoosterException as e:
                self._keys = {}
                raise StartGameException(str(e))
Exemple #19
0
    def __init__(
        self,
        options: t.Mapping[str, t.Any],
        players: t.AbstractSet[AbstractUser],
        callback: t.Callable[[], None],
    ):
        super().__init__(options, players, callback)
        self._pool_specification = PoolSpecification.from_options(
            self.pool_specification)

        self._keys = {
            user: drafter.key
            for user, drafter in DRAFT_COORDINATOR.start_draft(
                users=random.sample(list(self._players), len(self._players)),
                pool_specification=self._pool_specification,
                infinites=RawStrategy(db).deserialize(Infinites,
                                                      self.infinites),
                draft_format=self.draft_format,
                reverse=self.reverse,
                finished_callback=self._finished_callback_wrapper,
            )
        }
Exemple #20
0
 def from_native(self, value: str) -> T:
     return deserialize_cardboard_cubeable_string(value, RawStrategy(db))
Exemple #21
0
def serialize_cubeable(cubeable: Cubeable) -> t.Any:
    return cubeable.id if isinstance(
        cubeable, Printing) else RawStrategy.serialize(cubeable)
Exemple #22
0
def serialize_cardboard_cubeable(
        cardboard_cubeable: CardboardCubeable) -> t.Any:
    return cardboard_cubeable.name if isinstance(
        cardboard_cubeable,
        Cardboard) else RawStrategy.serialize(cardboard_cubeable)
Exemple #23
0
class DraftGame(Game):
    name = 'draft'

    format: str = metaoptions.OptionsOption(
        options=Format.formats_map.keys(),
        default=LimitedSideboard.name,
    )
    open_decks: bool = metaoptions.BooleanOption(default=False)
    open_pools: bool = metaoptions.BooleanOption(default=False)
    reverse: bool = metaoptions.BooleanOption(default=False)
    pool_specification: PoolSpecificationOptions = PoolSpecificationOption(
        {
            'CubeBoosterSpecification': {
                'release': CubeReleaseOption(),
                'size': metaoptions.IntegerOption(min=1, max=360, default=7),
                'allow_intersection': metaoptions.BooleanOption(default=False),
                'allow_repeat': metaoptions.BooleanOption(default=False),
                'scale': metaoptions.BooleanOption(default=False),
            },
            'ExpansionBoosterSpecification': {
                'expansion_code': ExpansionOption(),
            },
            'AllCardsBoosterSpecification': {
                'respect_printings': metaoptions.BooleanOption(default=True),
            },
            'ChaosBoosterSpecification': {
                'same': metaoptions.BooleanOption(default=False),
            },
        },
        default_booster_specification='CubeBoosterSpecification',
        default_amount=11,
    )
    draft_format: str = metaoptions.OptionsOption(
        options={'single_pick', 'burn'}, default='single_pick')
    infinites: t.Mapping[str, t.Any] = CardboardSetOption(
        default=RawStrategy.serialize(
            CardboardSet((db.cardboards[n] for n in (
                'Plains',
                'Island',
                'Swamp',
                'Mountain',
                'Forest',
            )))))
    allow_cheating = metaoptions.BooleanOption(default=False)
    tournament_options = TournamentOptions()

    def __init__(
        self,
        options: t.Mapping[str, t.Any],
        players: t.AbstractSet[AbstractUser],
        callback: t.Callable[[], None],
    ):
        super().__init__(options, players, callback)
        self._pool_specification = PoolSpecification.from_options(
            self.pool_specification)

        self._keys = {
            user: drafter.key
            for user, drafter in DRAFT_COORDINATOR.start_draft(
                users=random.sample(list(self._players), len(self._players)),
                pool_specification=self._pool_specification,
                infinites=RawStrategy(db).deserialize(Infinites,
                                                      self.infinites),
                draft_format=self.draft_format,
                reverse=self.reverse,
                finished_callback=self._finished_callback_wrapper,
            )
        }

    def _finished_callback_wrapper(self, draft: Draft):
        self._finished_callback()

        tournament_type, tournament_config, match_type = TournamentOptions.deserialize_options(
            self.tournament_options)

        session = LimitedSession.objects.create(
            game_type='draft',
            format=self.format,
            open_decks=self.open_decks,
            open_pools=self.open_pools,
            pool_specification=self._pool_specification,
            infinites=RawStrategy(db).deserialize(Infinites, self.infinites),
            allow_cheating=self.allow_cheating,
            tournament_type=tournament_type,
            tournament_config=tournament_config,
            match_type=match_type,
        )

        draft.draft_session.limited_session = session
        draft.draft_session.save(update_fields=('limited_session', ))

        if self.reverse:
            drafters = list(draft.interfaces.items())
            random.shuffle(drafters)
            for ((drafter, interface),
                 (_, next_interface)) in zip(drafters,
                                             drafters[1:] + [drafters[0]]):
                pool = Pool.objects.create(
                    user=drafter.user,
                    session=session,
                    pool=next_interface.pool,
                )
                interface.send_message(
                    'completed',
                    pool_id=pool.id,
                    session_name=session.name,
                )
        else:
            for drafter, interface in draft.interfaces.items():
                pool = Pool.objects.create(
                    user=drafter.user,
                    session=session,
                    pool=interface.pool,
                )
                interface.send_message(
                    'completed',
                    pool_id=pool.id,
                    session_name=session.name,
                )

    @property
    def keys(self) -> t.Mapping[AbstractUser, t.Union[str, int]]:
        return self._keys

    def start(self) -> None:
        pass
Exemple #24
0
    def _receive_message(self, message_type: str, content: t.Any) -> None:
        if not message_type == 'update':
            return

        if DISTRIBUTOR_SERVICE.is_patch_locked(self._patch_pk):
            self._send_message('status', status = 'locked')
            return

        with transaction.atomic():
            try:
                patch = (
                    models.CubePatch.objects
                        .select_for_update()
                        .get(pk = self._patch_pk)
                )
            except models.CubePatch.DoesNotExist:
                self._send_error(f'no patch with id {self._patch_pk}')
                self.close()
                return

            update = content.get('update')
            change_undoes = content.get('change_undoes')

            if not update and not change_undoes:
                self._send_error('update must have at least one of "updates" or "change_undoes" fields')
                return

            patch_update = CubePatch()

            if update:
                try:
                    update = RawStrategy(db).deserialize(
                        CubePatch,
                        update,
                    )
                except (KeyError, AttributeError):
                    self._send_error('bad request')
                    return

                patch_update += update

            if change_undoes:

                undoes: t.List[t.Tuple[cubeupdate.CubeChange, int]] = []
                try:
                    for undo, multiplicity in change_undoes:
                        undoes.append(
                            (
                                JsonId(db).deserialize(
                                    CUBE_CHANGE_MAP[undo['type']],
                                    undo['content'],
                                ),
                                multiplicity,
                            )
                        )
                except (KeyError, TypeError, ValueError):
                    traceback.print_exc()
                    self._send_error('bad request')
                    return

                for undo, multiplicity in undoes:
                    patch_update -= (undo.as_patch() * multiplicity)

            patch.patch += patch_update
            patch.save()

            meta_cube = patch.versioned_cube.latest_release.as_meta_cube()

            msg = {
                'type': 'cube_update',
                'update': {
                    'patch': orpserialize.CubePatchOrpSerializer.serialize(
                        patch.patch
                    ),
                    'verbose_patch': orpserialize.VerbosePatchSerializer.serialize(
                        patch.patch.as_verbose(
                            meta_cube
                        )
                    ),
                    'preview': orpserialize.MetaCubeSerializer.serialize(
                        meta_cube + patch.patch
                    ),
                    'updater': serializers.UserSerializer(self.scope['user']).data,
                    'update': orpserialize.VerbosePatchSerializer.serialize(
                        patch_update.as_verbose(
                            meta_cube
                        )
                    )
                },
            }

            async_to_sync(self.channel_layer.group_send)(
                self._group_name,
                msg,
            )
Exemple #25
0
class Sealed(Game):
    name = 'sealed'

    format: str = metaoptions.OptionsOption(options=Format.formats_map.keys(),
                                            default=LimitedSideboard.name)
    open_decks: bool = metaoptions.BooleanOption(default=False)
    open_pools: bool = metaoptions.BooleanOption(default=False)
    pool_specification: PoolSpecificationOptions = PoolSpecificationOption(
        {
            'CubeBoosterSpecification': {
                'release': CubeReleaseOption(),
                'size': metaoptions.IntegerOption(min=1, max=360, default=90),
                'allow_intersection': metaoptions.BooleanOption(default=False),
                'allow_repeat': metaoptions.BooleanOption(default=False),
                'scale': metaoptions.BooleanOption(default=False),
            },
            'ExpansionBoosterSpecification': {
                'expansion_code': ExpansionOption(),
            },
            'AllCardsBoosterSpecification': {
                'respect_printings': metaoptions.BooleanOption(default=True),
            },
            'ChaosBoosterSpecification': {
                'same': metaoptions.BooleanOption(default=False),
            },
        },
        default_booster_specification='CubeBoosterSpecification',
    )
    infinites: t.Mapping[str, t.Any] = CardboardSetOption(
        default=RawStrategy.serialize(
            CardboardSet((db.cardboards[n] for n in (
                'Plains',
                'Island',
                'Swamp',
                'Mountain',
                'Forest',
            )))))
    mirrored = metaoptions.BooleanOption(default=False)
    tournament_options = TournamentOptions()

    def __init__(
        self,
        options: t.Mapping[str, t.Any],
        players: t.AbstractSet[AbstractUser],
        callback: t.Callable[[], None],
    ):
        super().__init__(options, players, callback)

        tournament_type, tournament_config, match_type = TournamentOptions.deserialize_options(
            self.tournament_options)

        with transaction.atomic():
            pool_specification = PoolSpecification.from_options(
                self.pool_specification)
            session = LimitedSession.objects.create(
                game_type='sealed',
                format=self.format,
                open_decks=self.open_decks,
                open_pools=self.open_pools,
                pool_specification=pool_specification,
                infinites=RawStrategy(db).deserialize(Infinites,
                                                      self.infinites),
                tournament_type=tournament_type,
                tournament_config=tournament_config,
                match_type=match_type,
            )

            self._keys = {}

            try:
                for player, pool in zip(
                        players,
                        itertools.repeat(pool_specification.get_pool())
                        if self.mirrored else pool_specification.get_pools(
                            len(players))):
                    self._keys[player] = Pool.objects.create(
                        user=player,
                        session=session,
                        pool=pool,
                    ).id
            except GenerateBoosterException as e:
                self._keys = {}
                raise StartGameException(str(e))

    @property
    def keys(self) -> t.Mapping[AbstractUser, t.Union[str, int]]:
        return self._keys

    def start(self) -> None:
        self._finished_callback()
Exemple #26
0
 def serialize(self) -> t.Mapping[str, t.Any]:
     return {
         'pool': self._pool,
         'infinites': RawStrategy.serialize(self.infinites),
         **super().serialize(),
     }