Repository navigation
3. Спиридонов Олег Станиславович. 613 #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
69261b6
cd45379
16f0671
aebb72d
25bb0a9
ae4b181
8c6c49b
ae0fa32
6269b68
3eddba0
e4bdd11
83391b4
fb67ab9
e46602d
a0609e5
dbff7be
ddaf5c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,38 +1,21 @@ | ||
| """Bit layout and default epoch for the Twitter Snowflake ID generator. | ||
|
|
||
| A Snowflake identifier is a 63-bit positive integer packed as follows, from | ||
| the most significant bit downwards: | ||
|
|
||
| 1 bit unused sign bit, always zero | ||
| 41 bits milliseconds elapsed since a custom epoch | ||
| 10 bits node identifier | ||
| 12 bits per-millisecond sequence counter | ||
|
|
||
| The shift and mask constants should be derived from the bit widths so that | ||
| changing a width keeps everything else consistent. | ||
| """ | ||
|
|
||
| from typing import Final | ||
|
|
||
|
|
||
| # TODO: замените заглушки (0) на корректные значения, см. TASK.md. | ||
| # Все константы, зависящие от ёмкостей *_BITS, должны вычисляться из них. | ||
|
|
||
| # Twitter's original Snowflake epoch: 2010-11-04 01:42:54.657 UTC. | ||
| EPOCH_MS_DEFAULT: Final[int] = 0 | ||
| EPOCH_MS_DEFAULT: Final[int] = 1288834974657 | ||
|
|
||
| # Node identifier used when the caller does not supply one. | ||
| NODE_ID_DEFAULT: Final[int] = 0 | ||
| NODE_ID_DEFAULT: Final[int] = 1 | ||
|
|
||
| # Width of each field, in bits. | ||
| TIMESTAMP_BITS: Final[int] = 0 | ||
| NODE_ID_BITS: Final[int] = 0 | ||
| SEQUENCE_ID_BITS: Final[int] = 0 | ||
| TIMESTAMP_BITS: Final[int] = 41 | ||
| NODE_ID_BITS: Final[int] = 10 | ||
| SEQUENCE_ID_BITS: Final[int] = 12 | ||
|
|
||
| # Largest value each field can hold. | ||
| TIMESTAMP_MS_MAX: Final[int] = 0 | ||
| NODE_ID_MAX: Final[int] = 0 | ||
| SEQUENCE_ID_MAX: Final[int] = 0 | ||
| TIMESTAMP_MS_MAX: Final[int] = 2**TIMESTAMP_BITS - 1 | ||
| NODE_ID_MAX: Final[int] = 2**NODE_ID_BITS - 1 | ||
| SEQUENCE_ID_MAX: Final[int] = 2**SEQUENCE_ID_BITS - 1 | ||
|
|
||
| # Здесь можно добавить собственные вспомогательные константы | ||
| # (например, сдвиги полей при сборке идентификатора). | ||
| # (например, сдвиги полей при сборке идентификатора) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,8 +11,8 @@ | |
|
|
||
| from typing import Final | ||
|
|
||
| from .crud import read_product, update_product # noqa: F401 | ||
| from .storage import ( # noqa: F401 | ||
| from .crud import read_product, update_product | ||
| from .storage import ( | ||
| NAME_INDEX, | ||
| PRICE_INDEX, | ||
| QUANTITY_INDEX, | ||
|
|
@@ -22,9 +22,25 @@ | |
|
|
||
| type CartLine = tuple[int, int] | ||
|
|
||
| # TODO: задайте позиции полей внутри кортежа CartLine | ||
|
|
||
| LINE_PRODUCT_ID_INDEX: Final = 0 | ||
| LINE_QUANTITY_INDEX: Final = 0 | ||
| LINE_QUANTITY_INDEX: Final = 1 | ||
|
|
||
|
|
||
| def find_cart_line(cart: list[CartLine], product_id: int) -> CartLine | None: | ||
| for cartline in cart: | ||
| if cartline[LINE_PRODUCT_ID_INDEX] == product_id: | ||
| return cartline | ||
| return None | ||
|
|
||
|
|
||
| def change_cart_quantity( | ||
| cart: list[CartLine], cartline: CartLine, quantity: int | ||
| ) -> None: | ||
| cart.append( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Что-то вы перемудрили с обновлением значений. Зачем было каждый раз удалять и добавлять, если можно просто саму строку заменить cart[ind] = (cartline[LINE_PRODUCT_ID_INDEX], cartline[LINE_QUANTITY_INDEX] + quantity)У меня даже тесты упали, но пожалуй не буду снижать. |
||
| (cartline[LINE_PRODUCT_ID_INDEX], cartline[LINE_QUANTITY_INDEX] + quantity) | ||
| ) | ||
| cart.remove(cartline) | ||
|
|
||
|
|
||
| def add_to_cart( | ||
|
|
@@ -33,28 +49,31 @@ def add_to_cart( | |
| product_id: int, | ||
| quantity: int, | ||
| ) -> CartLine | None: | ||
| """Move ``quantity`` units of ``product_id`` from the store into ``cart``. | ||
|
|
||
| The product is looked up in ``storage``. If it is missing, a message is | ||
| printed (by :func:`~src.part2.crud.read_product`) and nothing | ||
| changes. If the store holds fewer units than requested, an explanatory | ||
| message is printed and nothing changes. Otherwise the store record is | ||
| decremented by ``quantity`` and the cart line for ``product_id`` gains | ||
| ``quantity`` units -- a new line is created when the cart had none. | ||
|
|
||
| Args: | ||
| storage: The product store to draw stock from; modified in place on | ||
| success. | ||
| cart: The cart to add the units to; modified in place on success. | ||
| product_id: The identifier of the product to add. | ||
| quantity: Number of units to move into the cart. | ||
|
|
||
| Returns: | ||
| The cart line for ``product_id`` after the addition, or ``None`` | ||
| when the product is unknown or the store cannot cover the request. | ||
| """ | ||
| # TODO: реализуйте функцию | ||
| return (0, 0) | ||
| requested_product = read_product(storage, product_id) | ||
| if requested_product is None: | ||
| return None | ||
| product_name = requested_product[NAME_INDEX] | ||
| product_price = requested_product[PRICE_INDEX] | ||
| product_amount = requested_product[QUANTITY_INDEX] | ||
|
|
||
| if product_amount < quantity: | ||
| print( | ||
| f"not enough stock for product {product_id}: {product_amount} available, {quantity} requested" | ||
| ) | ||
| return None | ||
|
|
||
| update_product( | ||
| storage, product_id, (product_name, product_price, product_amount - quantity) | ||
| ) | ||
|
|
||
| old_cartline = find_cart_line(cart, product_id) | ||
|
|
||
| if old_cartline is not None: | ||
| change_cart_quantity(cart, old_cartline, quantity) | ||
| else: | ||
| cart.append((product_id, quantity)) | ||
|
|
||
| return find_cart_line(cart, product_id) | ||
|
|
||
|
|
||
| def remove_from_cart( | ||
|
|
@@ -63,27 +82,38 @@ def remove_from_cart( | |
| product_id: int, | ||
| quantity: int, | ||
| ) -> CartLine | None: | ||
| """Move ``quantity`` units of ``product_id`` from ``cart`` back to the store. | ||
|
|
||
| The cart line for ``product_id`` is looked up. If there is none, a | ||
| message is printed and nothing changes. If the line holds fewer units | ||
| than requested, an explanatory message is printed and nothing changes. | ||
| Otherwise the cart line loses ``quantity`` units -- the line is dropped | ||
| when it reaches zero -- and the store record gains ``quantity`` units | ||
| back. | ||
|
|
||
| Args: | ||
| storage: The product store to return stock to; modified in place on | ||
| success. | ||
| cart: The cart to take the units from; modified in place on | ||
| success. | ||
| product_id: The identifier of the product to remove. | ||
| quantity: Number of units to move back into the store. | ||
|
|
||
| Returns: | ||
| The cart line for ``product_id`` after the removal (a quantity of | ||
| zero means the line was dropped), or ``None`` when the cart has no | ||
| line for the product or holds too few units. | ||
| """ | ||
| # TODO: реализуйте функцию | ||
| return (0, 0) | ||
| changable_cartline = find_cart_line(cart, product_id) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тут уже на грани пункта S2. Понимаю, что тут ruff постарался, но лучше было бы вынести какие-то вычисления на отдельные строки, чтобы избежать слишком длинных строк. Пока не снижаю, но чтобы больше я такого не видел. |
||
|
|
||
| if changable_cartline is None: | ||
| print(f"product {product_id} is not in the cart") | ||
| return None | ||
| if changable_cartline[LINE_QUANTITY_INDEX] < quantity: | ||
| print( | ||
| f"cart holds only {changable_cartline[LINE_QUANTITY_INDEX]} unit(s) of product {product_id}, cannot remove {quantity}" | ||
| ) | ||
| return None | ||
|
|
||
| storage_product = read_product(storage, product_id) | ||
| if storage_product is None: | ||
| return None | ||
|
|
||
| update_product( | ||
| storage, | ||
| product_id, | ||
| ( | ||
| storage_product[NAME_INDEX], | ||
| storage_product[PRICE_INDEX], | ||
| storage_product[QUANTITY_INDEX] + quantity, | ||
| ), | ||
| ) | ||
| change_cart_quantity(cart, changable_cartline, -quantity) | ||
| updated_cartline = find_cart_line(cart, product_id) | ||
|
|
||
| if updated_cartline is None: # проверка, чтобы mypy не ругался | ||
| return None | ||
|
|
||
| if updated_cartline[LINE_QUANTITY_INDEX] == 0: | ||
| cart.remove(updated_cartline) | ||
| return (product_id, 0) | ||
|
|
||
| return updated_cartline | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Вычисление сдвига дублировано в функции
decode_timestamp_ms. Это может быть опасно, так как если логика поменяется, то надо будет исправлять в 2х местах, а это можно забыть, поэтому лучше было вынести вычисление в отдельную константу.Пункт S1, минус балл.