예제 #1
0
class ToDoListOptions(Schema):
    project = fields.CoalesceField(
        [fields.Integer(), fields.Text()], default=None, required=False)
    tag = custom_fields.StringIdentifiedField(models.Tag,
                                              default=None,
                                              required=False)
    query = fields.Text(default='')
    all_tasks = fields.Bool(default=False)
    flat = fields.Bool(default=False)
    limit = fields.Integer(default=25)
    ignore_priority = fields.Bool(default=False)
    minimum_priority = fields.CoalesceField(
        [fields.Integer(), fields.Text()], default=None, required=False)
    state = fields.Enum(models.State,
                        soft_match=True,
                        required=False,
                        default=None)
    order_by = fields.List(
        fields.MultiChoiceField(
            {
                'created_at',
                'finished_at',
                'state',
                'priority',
                'project',
            },
            soft_match=True,
        ),
        required=False,
        default=None,
    )
예제 #2
0
class PrioritySchema(Schema[models.Priority]):
    id = fields.Integer(read_only=True)
    name = fields.Text(min=1, max=127, pattern=re.compile(r'\w+'))
    created_at = fields.Datetime(read_only=True)
    level = fields.Integer()
    project = fields.Lambda(lambda p: p.project.name)
    is_default = fields.Bool(default=False)
예제 #3
0
class CreateTodoSchema(Schema):
    tags = fields.List(
        fields.CoalesceField([
            fields.Integer(),
            fields.Text(min=1, max=127, pattern=re.compile(r'\w+')),
        ]),
        default=(),
    )
    project = fields.CoalesceField(
        [
            fields.Integer(),
            fields.Text(min=1, max=127, pattern=re.compile(r'\w+')),
        ],
        required=False,
    )
    parents = fields.List(
        fields.CoalesceField([
            fields.Integer(),
            fields.Text(),
        ]),
        default=(),
    )
    priority = fields.CoalesceField(
        [
            fields.Integer(),
            fields.Text(min=1, max=127, pattern=re.compile(r'\w+')),
        ],
        required=False,
    )
예제 #4
0
class StatsOptionsSchema(Schema):
    project = fields.CoalesceField(
        [fields.Integer(), fields.Text()], default=None, required=False)
    tag = custom_fields.StringIdentifiedField(models.Tag,
                                              default=None,
                                              required=False)
    top_level_only = fields.Bool(default=True)
    ignore_priority = fields.Bool(default=False)
    minimum_priority = fields.CoalesceField(
        [fields.Integer(), fields.Text()], default=None, required=False)
    last_n_days = fields.Integer(default=128)
예제 #5
0
class PickTableSchema(Schema[PickPoint]):
    global_pick_number = fields.Integer()
    pack_number = fields.Lambda(lambda p: p.round.pack)
    pick_number = fields.Integer()
    pick = fields.Lambda(
        lambda p: describe_focusable(p.pick.cubeable if isinstance(
            p.pick, SinglePickPick) else p.pick.pick))
    burn = fields.Lambda(
        lambda p: describe_focusable(p.pick.burn)
        if isinstance(p.pick, BurnPick) and p.pick.burn is not None else '')
    pack = fields.Lambda(
        lambda p: ', '.join(map(
            describe_focusable,
            p.booster.cubeables,
        )))
예제 #6
0
class AlarmSchema(Schema[models.Alarm]):
    id = fields.Integer(read_only=True)

    text = fields.Text()

    started_at = fields.Datetime(read_only=True)
    end_at = fields.Datetime()
    next_reminder_time_target = fields.Datetime(required=False, read_only=True)

    requires_acknowledgment = fields.Bool(required=False)
    retry_delay = fields.Integer(required=False, min=5)
    send_email = fields.Bool(required=False)
    silent = fields.Bool(required=False)
    level = fields.Enum(models.ImportanceLevel, required=False)

    times_notified = fields.Integer(read_only=True)
    acknowledged = fields.Bool(read_only=True)

    canceled = fields.Bool(read_only=True)
    success = fields.Bool(read_only=True)
예제 #7
0
class FirstToN(MatchOfn):
    name = 'FTN'
    options_schema = Schema({'n': fields.Integer(min = 1, max = 128, default = 2)})

    def validate_result(self, result: CompletedMatch) -> Errors:
        errors = []
        max_wins = max(result.results.values())
        if max_wins != self._n:
            errors.append(
                'match not completed, leader has {} wins, which does not match required {}.'.format(
                    max_wins,
                    self._n,
                )
            )
        if len(result.winners) > 1:
            errors.append('match cannot be a draw')
        return Errors(errors)
예제 #8
0
class ToDoSchema(Schema[models.ToDo]):
    id = fields.Integer(read_only=True)

    text = fields.Text()

    tags = fields.Lambda(lambda todo: [tag.name for tag in todo.tags])
    comments = fields.Lambda(
        lambda todo: [comment.text for comment in todo.comments])
    project = fields.Lambda(lambda todo: todo.project.name)

    priority = fields.Related(PrioritySchema(), read_only=True)

    created_at = fields.Datetime(read_only=True)
    finished_at = fields.Datetime(read_only=True)

    state = fields.Enum(models.State, read_only=True)

    children = fields.List(fields.SelfRelated(),
                           read_only=True,
                           source='active_children')
예제 #9
0
class MatchOfn(MatchType):
    options_schema = Schema({'n': fields.Integer(min = 1, max = 128, default = 3)})

    def __init__(self, n: int, **kwargs):
        super().__init__(**kwargs)
        self._n = n

    @property
    def n(self) -> int:
        return self._n

    def __str__(self) -> str:
        return f'{self.name}{self._n}'

    def _serialize_args(self) -> t.Mapping[str, t.Any]:
        return {'n': self._n}

    @abstractmethod
    def validate_result(self, result: CompletedMatch) -> Errors:
        pass
예제 #10
0
파일: grid.py 프로젝트: guldfisk/deckeditor
class GridAligner(Aligner):
    name = 'Grid'
    schema = Schema(
        fields={
            'columns': fields.Integer(default=5, min=1, max=64),
            # 'margin': fields.Float(default = .05, min = 0., max = 1.),
        }, )

    def __init__(self,
                 scene: SelectionScene,
                 columns: int = 5,
                 margin: float = .05):
        super().__init__(scene)

        self._margin = int(IMAGE_WIDTH * margin)
        self._columns = columns

        self._cards: t.List[PhysicalCard] = []

    @property
    def options(self) -> t.Mapping[str, t.Any]:
        return {
            'columns': self._columns,
        }

    @property
    def cards(self) -> t.List[PhysicalCard]:
        return self._cards

    @property
    def supports_sort_orientation(self) -> bool:
        return False

    @property
    def supports_sub_sort(self) -> bool:
        return False

    def pick_up(self, items: t.Iterable[PhysicalCard]) -> GridPickUp:
        return GridPickUp(
            self,
            items,
        )

    def get_position_at_index(self, idx: int) -> QPoint:
        return QPoint(
            max(
                (idx % self._columns) * (IMAGE_WIDTH + self._margin),
                0,
            ),
            max(
                (idx // self._columns) * (IMAGE_HEIGHT + self._margin),
                0,
            ),
        )

    def map_position_to_index(self, position: QPoint) -> int:
        return min(
            int(position.x() // (IMAGE_WIDTH + self._margin) +
                (position.y() //
                 (IMAGE_HEIGHT + self._margin) * self._columns)),
            len(self._cards),
        )

    def realign(self, from_index: int = 0) -> None:
        from_index = max(from_index, 0)
        for card, idx in zip(self._cards[from_index:],
                             range(from_index, len(self._cards))):
            card.setPos(self.get_position_at_index(idx))

    def drop(self, items: t.Iterable[PhysicalCard],
             position: QPoint) -> GridDrop:
        return GridDrop(
            self,
            items,
            position,
        )

    def multi_drop(
        self, drops: t.Sequence[t.Tuple[t.Sequence[PhysicalCard], QPoint]]
    ) -> GridMultiDrop:
        return GridMultiDrop(
            self,
            drops,
        )

    def sort(self,
             sort_macro: SortMacro,
             cards: t.Sequence[PhysicalCard],
             in_place: bool = False) -> QUndoCommand:
        return GridSort(
            grid=self,
            specifications=list(
                itertools.chain(*(specifications
                                  for dimension, specifications in
                                  sort_macro.dimension_specifications_map))),
            cards=cards,
            original_order=copy.copy(self._cards),
            in_place=in_place,
        )

    def context_menu(self, menu: QtWidgets.QMenu, position: QPoint,
                     undo_stack: QUndoStack) -> None:
        resize_action = QtWidgets.QAction('Set Column Count', menu)
        resize_action.triggered.connect(
            lambda: self.update_column_count(menu, undo_stack))
        menu.addAction(resize_action)

    def update_column_count(self, parent: QtWidgets.QWidget,
                            undo_stack: QUndoStack) -> None:
        amount, ok = QInputDialog.getInt(
            parent,
            'Choose new column count',
            '',
            self._columns,
            1,
            64,
        )
        if ok:
            undo_stack.push(SetColumnCount(
                self,
                amount,
            ))
예제 #11
0
class StackingGrid(Aligner):
    _show_grid = False
    schema = Schema(
        fields = {
            'rows': fields.Integer(default = 3, min = 1, max = 64),
            'columns': fields.Integer(default = 15, min = 1, max = 64),
            # 'margin': fields.Float(default = STANDARD_IMAGE_MARGIN, min = 0., max = 1.),
            'show_grid': fields.Bool(default = False),
        },
    )

    def __init__(
        self,
        scene: SelectionScene,
        *,
        rows: int = 5,
        columns: int = 5,
        margin: float = STANDARD_IMAGE_MARGIN,
        show_grid: bool = False,
    ):
        super().__init__(scene)

        self._stacked_cards: t.Dict[PhysicalCard, _CardInfo] = {}
        self._margin_pixel_size = margin * IMAGE_WIDTH
        self._stacker_map = self.create_stacker_map(rows, columns)
        self._show_grid = show_grid

    @property
    def options(self) -> t.Mapping[str, t.Any]:
        return {
            'rows': self._stacker_map.column_height,
            'columns': self._stacker_map.row_length,
            'show_grid': self._show_grid,
        }

    @abstractmethod
    def create_stacker_map(self, rows: int, columns: int) -> StackerMap:
        pass

    @abstractmethod
    def request_space(self, card_stacker: CardStacker, x: int, y: int) -> None:
        pass

    @abstractmethod
    def create_stacker(self, x: int, y: int) -> CardStacker:
        pass

    @property
    def stacker_map(self) -> StackerMap:
        return self._stacker_map

    @property
    def stacked_cards(self) -> t.Dict[PhysicalCard, _CardInfo]:
        return self._stacked_cards

    @property
    def cards(self) -> t.Iterable[PhysicalCard]:
        for stacker in self._stacker_map.stackers:
            yield from stacker.cards

    def realign(self) -> None:
        for stacker in self._stacker_map:
            stacker.update()

    def get_card_info(self, card: PhysicalCard) -> _CardInfo:
        try:
            return self._stacked_cards[card]
        except KeyError:
            self._stacked_cards[card] = info = _CardInfo()
            return info

    def remove_card(self, card: PhysicalCard) -> None:
        try:
            del self._stacked_cards[card]
        except KeyError:
            pass

    def pick_up(self, items: t.Iterable[PhysicalCard]) -> StackingPickUp:
        return StackingPickUp(
            self,
            items,
        )

    def drop(self, items: t.Iterable[PhysicalCard], position: QPoint) -> StackingDrop:
        x, y = position.x(), position.y()
        stacker = self.get_card_stacker(x, y)
        index = stacker.map_position_to_index(x - stacker.x, y - stacker.y)
        return StackingDrop(
            self,
            stacker,
            index,
            tuple(items),
        )

    def multi_drop(self, drops: t.Iterable[t.Tuple[t.Sequence[PhysicalCard], QPoint]]) -> StackingMultiDrop:
        _drops = []
        for cards, position in drops:
            x, y = position.x(), position.y()
            stacker = self.get_card_stacker(x, y)
            index = stacker.map_position_to_index(x - stacker.x, y - stacker.y)
            _drops.append(
                (
                    cards,
                    stacker,
                    index,
                )
            )

        return StackingMultiDrop(self, _drops)

    def get_card_stacker_at_index(self, x: int, y: int) -> CardStacker:
        return self.stacker_map.get_stacker(
            minmax(0, x, self.stacker_map.row_length - 1),
            minmax(0, y, self.stacker_map.column_height - 1),
        )

    def get_card_stacker(self, x: int, y: int) -> CardStacker:
        return self.get_card_stacker_at_index(
            *self._stacker_map.map_position_to_index(x, y)
        )

    def sort(self, sort_macro: SortMacro, cards: t.Sequence[PhysicalCard], in_place: bool = False) -> QUndoCommand:
        commands = []
        for dimension, specifications in sort_macro.dimension_specifications_map:
            continuity = sort_macro.continuity_for_dimension(dimension)
            if continuity == DimensionContinuity.AUTO:
                if len(specifications) == 1:
                    continuity = continuity.continuity_for(specifications[0].sort_property)
                else:
                    continuity = DimensionContinuity.CONTINUOUS

            if dimension == SortDimension.SUB_DIVISIONS:
                commands.append(
                    SortAllStackers(
                        grid = self,
                        specifications = specifications,
                    )
                )

            else:
                commands.append(
                    (
                        ContinuousSort
                        if continuity == DimensionContinuity.CONTINUOUS else
                        GroupedSort
                    )(
                        grid = self,
                        cards = cards,
                        specifications = specifications,
                        orientation = QtCore.Qt.Horizontal if dimension == SortDimension.HORIZONTAL else QtCore.Qt.Vertical,
                        in_place = in_place,
                    )
                )

        if len(commands) == 1:
            return commands[0]

        return CommandPackage(commands)

    @classmethod
    def _get_sort_stack(
        cls,
        stacker: CardStacker,
        sort_property: t.Type[sorting.SortProperty],
        undo_stack: QUndoStack,
    ) -> t.Callable[[], None]:
        def _sort_stack() -> None:
            undo_stack.push(
                SortStacker(
                    stacker = stacker,
                    specifications = [sorting.SortSpecification(sort_property = sort_property)],
                )
            )

        return _sort_stack

    def _get_all_sort_stacker(
        self,
        sort_property: t.Type[sorting.SortProperty],
        undo_stack: QUndoStack,
    ) -> t.Callable[[], None]:
        def _sort_all_stackers() -> None:
            undo_stack.push(
                SortAllStackers(
                    grid = self,
                    specifications = [sorting.SortSpecification(sort_property = sort_property)],
                )
            )

        return _sort_all_stackers

    def insert_row(self, idx: int) -> QUndoCommand:
        pass

    def insert_column(self, idx: int) -> QUndoCommand:
        pass

    def _set_show_grid(self, show_grid: bool) -> None:
        self._show_grid = show_grid

    def context_menu(self, menu: QtWidgets.QMenu, position: QPoint, undo_stack: QUndoStack) -> None:
        stacker = self.get_card_stacker(position.x(), position.y())

        stacker_sort_menu = menu.addMenu('Sort Stack')

        for sort_property in sorting.SortProperty.names_to_sort_property.values():
            sort_action = QtWidgets.QAction(sort_property.name, stacker_sort_menu)
            sort_action.triggered.connect(self._get_sort_stack(stacker, sort_property, undo_stack))
            stacker_sort_menu.addAction(sort_action)

        all_stacker_sort_menu = menu.addMenu('Sort All Stack')

        for sort_property in sorting.SortProperty.names_to_sort_property.values():
            all_sort_action = QtWidgets.QAction(sort_property.name, all_stacker_sort_menu)
            all_sort_action.triggered.connect(self._get_all_sort_stacker(sort_property, undo_stack))
            all_stacker_sort_menu.addAction(all_sort_action)

        resize_action = QtWidgets.QAction('Resize grid', menu)
        resize_action.triggered.connect(lambda: self.resize(undo_stack))
        menu.addAction(resize_action)

        toggle_grid_action = QtWidgets.QAction('Hide Grid' if self._show_grid else 'Show Grid', menu)
        toggle_grid_action.triggered.connect(lambda: self._set_show_grid(not self._show_grid))
        menu.addAction(toggle_grid_action)

    def resize(self, undo_stack: QUndoStack) -> None:
        dialog = GridResizeDialog(self)
        dialog.exec_()
        if dialog.accepted:
            undo_stack.push(
                GridResize(
                    self,
                    *reversed(dialog.get_values()),
                )
            )

    def draw_background(self, painter: QtGui.QPainter, rect: QtCore.QRectF) -> None:
        if not self._show_grid:
            return

        painter.setPen(
            QtGui.QPen(
                QtGui.QColor(0, 0, 0)
            )
        )

        lines = []

        for x in list(self.stacker_map.row_termination_points())[:-1]:
            if rect.left() <= x <= rect.right():
                lines.append(
                    QLineF(
                        x, rect.top(), x, rect.bottom(),
                    )
                )

        for y in list(self.stacker_map.column_termination_points())[:-1]:
            if rect.top() <= y <= rect.bottom():
                lines.append(
                    QLineF(
                        rect.left(), y, rect.right(), y,
                    )
                )

        painter.drawLines(lines)
예제 #12
0
파일: projects.py 프로젝트: guldfisk/fml
    try:
        SC.session.commit()
    except IntegrityError:
        SC.session.rollback()
        return 'Project already exists', status.HTTP_400_BAD_REQUEST

    return schema.serialize(project)


@todo_project_views.route('/project/', methods = ['PATCH'])
@inject_schema(
    Schema(
        {
            'project': StringIdentifiedField(models.Project),
            'default_priority_filter': fields.CoalesceField(
                [fields.Integer(), fields.Text()],
                default = None,
                required = False,
            ),
        }
    ),
    use_args = False,
)
def modify_project(project: models.Project, default_priority_filter: t.Union[int, str, None]):
    if default_priority_filter is not None:
        default_priority_filter = get_priority_level(SC.session, default_priority_filter, project)
    project.default_priority_filter = default_priority_filter
    SC.session.commit()
    return schemas.ProjectSchema().serialize(project)

예제 #13
0
class Swiss(Tournament[P]):
    name = 'swiss'
    options_schema = Schema(
        {'rounds': fields.Integer(min=1, max=128, default=3)})
    allow_match_draws: bool = True

    def __init__(self,
                 players: t.FrozenSet[P],
                 rounds: int,
                 seed_map: t.Mapping[P, float] = immutabledict(),
                 **kwargs):
        super().__init__(players, seed_map, **kwargs)
        self._rounds = rounds

    @property
    def round_amount(self) -> int:
        return self._rounds

    def _get_ranked_players(
        self,
        previous_rounds: t.Sequence[CompletedRound[P]],
    ) -> t.Tuple[t.Sequence[t.Tuple[P, int]], t.Mapping[P, int]]:
        match_wins_map = defaultdict(int)
        game_wins_map = defaultdict(int)
        buys_map = defaultdict(int)

        for _round in previous_rounds:
            for result in _round.results:
                if len(result.results) == 1:
                    buys_map[result.results.__iter__().__next__()] += 1
                else:
                    for player, wins in result.results.items():
                        game_wins_map[player] += wins
                winners = result.winners
                if len(winners) == 1:
                    match_wins_map[winners.__iter__().__next__()] += 1

        opponent_match_wins_map = defaultdict(int)
        opponent_game_win_percentage = defaultdict(int)

        for _round in previous_rounds:
            for result in _round.results:
                if len(result.results) == 1:
                    continue

                for player, opponent in itertools.permutations(
                        result.results.keys()):
                    opponent_match_wins_map[player] += match_wins_map[opponent]
                    opponent_game_win_percentage[player] += game_wins_map[
                        opponent]

        ranked_players = sorted(
            [(player, (
                match_wins_map[player],
                opponent_match_wins_map[player],
                game_wins_map[player],
                opponent_game_win_percentage[player],
                -buys_map[player],
                -self._seed_map.get(player, 0),
            )) for player in self._players],
            key=lambda p: p[1],
            reverse=True,
        )

        result = []

        for idx, chunk in enumerate(
                more_itertools.split_when(
                    ranked_players,
                    lambda a, b: a[1] != b[1],
                )):
            for p, _ in chunk:
                result.append((p, idx))

        return result, buys_map

    def get_round(
        self, previous_rounds: t.Sequence[CompletedRound[P]] = ()
    ) -> t.Optional[Round[P]]:
        if len(previous_rounds) >= self._rounds:
            return None

        if not previous_rounds:
            buys_map = defaultdict(int)
            ranked_players = interleave(
                sorted(self._players,
                       key=lambda p:
                       (self._seed_map.get(p, 0), random.random())), )
        else:
            _ranked_players, buys_map = self._get_ranked_players(
                previous_rounds)

            ranked_players = []

            for players in more_itertools.split_when(
                    reversed(_ranked_players), lambda a, b: a[1] != b[1]):
                random.shuffle(players)
                for p, _ in players:
                    ranked_players.append(p)

        matches = []

        if len(ranked_players) & 1:
            min_buys = min(buys_map[player] for player in self._players)
            for player in reversed(ranked_players):
                if buys_map[player] == min_buys:
                    matches.append(
                        ScheduledMatch(
                            frozenset((ranked_players.pop(
                                ranked_players.index(player)), ))))
                    break

        for idx in range(0, len(ranked_players), 2):
            matches.append(
                ScheduledMatch(frozenset(ranked_players[idx:idx + 2])))

        return Round(frozenset(matches))

    def get_ranked_players(
        self, previous_rounds: t.Sequence[CompletedRound[P]]
    ) -> t.Sequence[t.Collection[P]]:
        ranked_players, _ = self._get_ranked_players(previous_rounds)
        return [[p for p, _ in tier] for tier in more_itertools.split_when(
            ranked_players, lambda a, b: a[1] != b[1])]

    def get_result(
            self, previous_rounds: t.Sequence[CompletedRound[P]]
    ) -> TournamentResult[P]:
        if len(previous_rounds) < self._rounds:
            raise ResultException('tournament not complete')
        return super().get_result(previous_rounds)
예제 #14
0
class TagSchema(Schema[models.Tag]):
    id = fields.Integer(read_only=True)
    name = fields.Text(min=1, max=127, pattern=re.compile(r'\w+'))
    created_at = fields.Datetime(read_only=True)
예제 #15
0
class AlarmListOptions(Schema):
    limit = fields.Integer(default=25)
    query = fields.CoalesceField(
        [fields.Integer(), fields.Text()], default=None, required=False)
예제 #16
0
class CommentSchema(Schema):
    target = fields.CoalesceField([fields.Integer(), fields.Text()])
    project = custom_fields.StringIdentifiedField(models.Project, default=None)
    comment = fields.Text()
예제 #17
0
class TaggedSchema(Schema[models.Tagged]):
    todo_target = fields.CoalesceField([fields.Integer(), fields.Text()])
    tag_target = custom_fields.StringIdentifiedField(models.Tag)
    project = custom_fields.StringIdentifiedField(models.Project, default=None)
    recursive = fields.Bool(default=False, write_only=True)
예제 #18
0
class ProjectSchema(Schema[models.Project]):
    id = fields.Integer(read_only=True)
    name = fields.Text(min=1, max=127, pattern=re.compile(r'\w+'))
    created_at = fields.Datetime(read_only=True)
    is_default = fields.Bool(default=False)
    default_priority_filter = fields.Integer(default=None, required=False)
예제 #19
0
class ModifyPrioritySchema(Schema[models.Tagged]):
    todo = fields.CoalesceField([fields.Integer(), fields.Text()])
    project = custom_fields.StringIdentifiedField(models.Project, default=None)
    priority = fields.CoalesceField([fields.Integer(), fields.Text()])
    recursive = fields.Bool(default=False, write_only=True)
예제 #20
0
class ModifyToDoSchema(Schema):
    target = fields.CoalesceField([fields.Integer(), fields.Text()])
    project = custom_fields.StringIdentifiedField(models.Project, default=None)
    description = fields.Text()