Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 38 additions & 67 deletions src/part5/cart.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,4 @@
"""Shopping-cart operations layered on top of the product store.

The cart is a plain dictionary mapping each product identifier to the
number of units of that product in the cart. Moving units between the
store and the cart keeps the two sides in balance: :func:`add_to_cart` takes
units out of stock, :func:`remove_from_cart` puts them back.

Like the CRUD layer, the failure path never raises -- the operation prints
an explanatory message to stdout and returns ``None``.
"""

from .storage import Product


# TODO: при необходимости добавьте свои вспомогательные функции
from .storage import QUANTITY_KEY, Product


def add_to_cart(
Expand All @@ -22,33 +8,22 @@ def add_to_cart(
product_id: int,
quantity: int,
) -> int | None:
"""Move ``quantity`` units of ``product_id`` from the store into ``cart``.
if product_id not in storage:
print(f"no product with id {product_id}")
return None

The product is looked up in ``storage``. If it is missing, a message is
printed (by :func:`~src.part5.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 gains ``quantity`` units of
``product_id`` -- the product is added when the cart had none of it.
storage_quantity = storage[product_id][QUANTITY_KEY]
if quantity > storage_quantity:
print(
f"not enough stock for product {product_id}: "
f"{storage_quantity} available, {quantity} requested"
)
return None

Args:
storage: The product store to draw stock from; modified in place on
success.
product_names: The normalised names in ``storage``; threaded
through to :func:`~src.part5.crud.update_product`, which
keeps it in sync (a quantity-only update never renames a
product, so it is left unchanged here).
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.
storage[product_id][QUANTITY_KEY] -= quantity
cart[product_id] = cart.get(product_id, 0) + quantity

Returns:
The quantity of ``product_id`` in the cart after the addition, or
``None`` when the product is unknown or the store cannot cover the
request.
"""
# TODO: реализуйте функцию (используйте своё решение части 4)
return 0
return cart[product_id]


def remove_from_cart(
Expand All @@ -58,31 +33,27 @@ def remove_from_cart(
product_id: int,
quantity: int,
) -> int | None:
"""Move ``quantity`` units of ``product_id`` from ``cart`` back to the store.

If the cart holds no units of ``product_id``, a message is printed and
nothing changes. If it holds fewer units than requested, an explanatory
message is printed and nothing changes. Otherwise the cart loses
``quantity`` units of the product -- the product is dropped from the
cart when its quantity reaches zero -- and the store record gains
``quantity`` units back.

Args:
storage: The product store to return stock to; modified in place on
success.
product_names: The normalised names in ``storage``; threaded
through to :func:`~src.part5.crud.update_product`, which
keeps it in sync (a quantity-only update never renames a
product, so it is left unchanged here).
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 quantity of ``product_id`` left in the cart after the removal
(zero means the product was dropped from the cart), or ``None`` when
the cart does not hold the product or holds too few units.
"""
# TODO: реализуйте функцию (используйте своё решение части 4)
return 0
if product_id not in cart:
print(f"product {product_id} is not in the cart")
return None

cart_quantity = cart[product_id]
if quantity > cart_quantity:
print(
f"cart holds only {cart_quantity} unit(s) of product {product_id},"
f" cannot remove {quantity}"
)
return None

if product_id not in storage:
print(f"no product with id {product_id}")
return None

storage[product_id][QUANTITY_KEY] += quantity
cart[product_id] -= quantity

if cart[product_id] == 0:
del cart[product_id]
return 0

return cart[product_id]
42 changes: 8 additions & 34 deletions src/part5/constants.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,11 @@
"""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) на корректные значения (используйте своё решение
# части 1).

# Twitter's original Snowflake epoch: 2010-11-04 01:42:54.657 UTC.
EPOCH_MS_DEFAULT: Final[int] = 0

# Node identifier used when the caller does not supply one.
NODE_ID_DEFAULT: Final[int] = 0

# Width of each field, in bits.
TIMESTAMP_BITS: Final[int] = 0
NODE_ID_BITS: Final[int] = 0
SEQUENCE_ID_BITS: Final[int] = 0

# Largest value each field can hold.
TIMESTAMP_MS_MAX: Final[int] = 0
NODE_ID_MAX: Final[int] = 0
SEQUENCE_ID_MAX: Final[int] = 0

# Здесь можно добавить собственные вспомогательные константы
EPOCH_MS_DEFAULT: Final[int] = 1288834974657
NODE_ID_DEFAULT: Final[int] = 1
TIMESTAMP_BITS: Final[int] = 41
NODE_ID_BITS: Final[int] = 10
SEQUENCE_ID_BITS: Final[int] = 12
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
Loading
Loading