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
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)), )
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'], ))))
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)
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
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)
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']), )
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, )
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(), ))
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, )
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, ))), }, )
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)
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, }
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}, )
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
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)
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
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))
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 from_native(self, value: str) -> T: return deserialize_cardboard_cubeable_string(value, RawStrategy(db))
def serialize_cubeable(cubeable: Cubeable) -> t.Any: return cubeable.id if isinstance( cubeable, Printing) else RawStrategy.serialize(cubeable)
def serialize_cardboard_cubeable( cardboard_cubeable: CardboardCubeable) -> t.Any: return cardboard_cubeable.name if isinstance( cardboard_cubeable, Cardboard) else RawStrategy.serialize(cardboard_cubeable)
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
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, )
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()
def serialize(self) -> t.Mapping[str, t.Any]: return { 'pool': self._pool, 'infinites': RawStrategy.serialize(self.infinites), **super().serialize(), }