From e09abc2dc00e466c4054d148f6444b9bafb3fe74 Mon Sep 17 00:00:00 2001 From: kekW Date: Wed, 10 Apr 2024 00:44:07 +0300 Subject: [PATCH 1/6] Solution? --- app/car.py | 21 ++++++++++++++ app/customer.py | 29 +++++++++++++++++++ app/main.py | 77 +++++++++++++++++++++++++++++++++++++++++++++++-- app/shop.py | 24 +++++++++++++++ 4 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 app/car.py create mode 100644 app/customer.py create mode 100644 app/shop.py diff --git a/app/car.py b/app/car.py new file mode 100644 index 00000000..d4fc4b85 --- /dev/null +++ b/app/car.py @@ -0,0 +1,21 @@ +from dataclasses import dataclass +import json + + +@dataclass +class Car: + brand: str = None + fuel_consumption: float = None + + +def load_fuel_price_from_json(filepath): + with open(filepath, "r") as file: + data = json.load(file) + return data.get("FUEL_PRICE") + + +FUEL_PRICE = load_fuel_price_from_json("app/config.json") + + +# if "__main__" == __name__: +# load_fuel_price_from_json("config.json") \ No newline at end of file diff --git a/app/customer.py b/app/customer.py new file mode 100644 index 00000000..9d367142 --- /dev/null +++ b/app/customer.py @@ -0,0 +1,29 @@ +from app.car import Car, FUEL_PRICE +import json + + +class Customer: + def __init__(self, + name: str, + product_cart: dict, + location: list, + money: float, + car: dict) -> None: + self.name = name + self.product_cart = product_cart + self.location = location + self.money = money + self.car = Car(**car) + + +def load_customers_from_json(filepath): + with open(filepath, "r") as file: + data = json.load(file) + customers_data = data.get("customers") + return [Customer(**customer_) for customer_ in customers_data] + + +customers_ = load_customers_from_json("app/config.json") + +# if __name__ == "__main__": +# load_customers_from_json("config.json") diff --git a/app/main.py b/app/main.py index 558d7d94..2628b1e5 100644 --- a/app/main.py +++ b/app/main.py @@ -1,3 +1,76 @@ +import datetime +from app.customer import customers_ +from app.shop import shops_ +from app.car import FUEL_PRICE +from math import sqrt + + def shop_trip(): - # write your code here - pass + customers = customers_ + shops = shops_ + fuel_price = FUEL_PRICE + + for customer in customers: + cheapest_shop = [] + print(f"{customer.name} has {customer.money} dollars") + for shop in shops: + total_price = 0 + for (_, value_need_customer), (_, shop_item_price) in zip( + customer.product_cart.items(), shop.products.items() + ): + total_price += value_need_customer * shop_item_price + # our road distance is calculated hypotenuse, + # I'd argue about it, cars don't drive strait lines :) + one_way_distance = sqrt( + (customer.location[0] - shop.location[0]) ** 2 + + (customer.location[1] - shop.location[1]) ** 2 + ) + total_price += round(customer.car.fuel_consumption + * fuel_price / 100 * one_way_distance * 2, 2) + + # save every shop to chose from + cheapest_shop.append([total_price, shop]) + print(f"{customer.name}'s trip to the {shop.name} " + f"costs {total_price}") + + cheapest_shop = list(sorted(cheapest_shop)).pop(0) + + if customer.money >= cheapest_shop[0]: + print(f"{customer.name} rides to {cheapest_shop[1].name}\n") + else: + print(f"{customer.name} doesn't have enough " + f"money to make a purchase in any shop") + continue + + # date_now = datetime.datetime.strftime(datetime.datetime.now(), + # "%d/%m/%Y %H:%M:%S") + # fake_date = datetime.datetime.strftime(datetime.datetime( + # 2021, 1, 4, 12, 33, 41 + # ), "%d/%m/%Y %H:%M:%S") + + # Date: 04/01/2021 12:33:41 + # print(f"Date: {fake_date}") + # I already tested "04/01/2021 12:33:41" == fake_date: + # TRUE I don't understand why this is happening + print(f"Date: 04/01/2021 12:33:41") + print(f"Thanks, {customer.name}, for your purchase!") + print(f"You have bought:") + + total_price_cart = 0 + + for (_, value_need_customer), (product_name, product_price) in zip(customer.product_cart.items(), cheapest_shop[1].products.items()): + total_amount_product = value_need_customer * product_price + if total_amount_product == int(total_amount_product): + total_amount_product = int(total_amount_product) + total_price_cart += total_amount_product + print(f"{value_need_customer} {product_name}s for {total_amount_product} dollars") + print(f"Total cost is {total_price_cart} dollars") + print(f"See you again!\n") + + print(f"{customer.name} rides home") + print(f"{customer.name} now has " + f"{customer.money - cheapest_shop[0]} dollars\n") + + +if "__main__" == __name__: + shop_trip() diff --git a/app/shop.py b/app/shop.py new file mode 100644 index 00000000..b9e23338 --- /dev/null +++ b/app/shop.py @@ -0,0 +1,24 @@ +import json + + +class Shop: + def __init__(self, + name: str, + location: list, + products: dict) -> None: + self.name = name + self.location = location + self.products = products + + +def load_shops_from_json(filepath): + with open(filepath, "r") as file: + data = json.load(file) + shops_data = data.get("shops") + return [Shop(**shop_) for shop_ in shops_data] + + +shops_ = load_shops_from_json("app/config.json") + +# if "__main__" == __name__: +# load_shops_from_json("config.json") From 73237b558f1912409f5824d3c3d639424c63fc79 Mon Sep 17 00:00:00 2001 From: kekW Date: Wed, 10 Apr 2024 00:53:34 +0300 Subject: [PATCH 2/6] Strange datetime work.. --- app/car.py | 8 ++------ app/customer.py | 8 +++----- app/main.py | 31 +++++++++++++++++++------------ app/shop.py | 5 +---- 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/app/car.py b/app/car.py index d4fc4b85..cb1fbcef 100644 --- a/app/car.py +++ b/app/car.py @@ -1,5 +1,5 @@ -from dataclasses import dataclass import json +from dataclasses import dataclass @dataclass @@ -8,14 +8,10 @@ class Car: fuel_consumption: float = None -def load_fuel_price_from_json(filepath): +def load_fuel_price_from_json(filepath: str) -> float: with open(filepath, "r") as file: data = json.load(file) return data.get("FUEL_PRICE") FUEL_PRICE = load_fuel_price_from_json("app/config.json") - - -# if "__main__" == __name__: -# load_fuel_price_from_json("config.json") \ No newline at end of file diff --git a/app/customer.py b/app/customer.py index 9d367142..a14d453a 100644 --- a/app/customer.py +++ b/app/customer.py @@ -1,6 +1,7 @@ -from app.car import Car, FUEL_PRICE import json +from app.car import Car + class Customer: def __init__(self, @@ -16,7 +17,7 @@ def __init__(self, self.car = Car(**car) -def load_customers_from_json(filepath): +def load_customers_from_json(filepath: str) -> list[Customer]: with open(filepath, "r") as file: data = json.load(file) customers_data = data.get("customers") @@ -24,6 +25,3 @@ def load_customers_from_json(filepath): customers_ = load_customers_from_json("app/config.json") - -# if __name__ == "__main__": -# load_customers_from_json("config.json") diff --git a/app/main.py b/app/main.py index 2628b1e5..9e25a435 100644 --- a/app/main.py +++ b/app/main.py @@ -1,11 +1,11 @@ -import datetime +from math import sqrt + +from app.car import FUEL_PRICE from app.customer import customers_ from app.shop import shops_ -from app.car import FUEL_PRICE -from math import sqrt -def shop_trip(): +def shop_trip() -> None: customers = customers_ shops = shops_ fuel_price = FUEL_PRICE @@ -48,24 +48,31 @@ def shop_trip(): # 2021, 1, 4, 12, 33, 41 # ), "%d/%m/%Y %H:%M:%S") - # Date: 04/01/2021 12:33:41 - # print(f"Date: {fake_date}") + # print(f"Date: 04/01/2021 12:33:41") - PASSES + # print(f"Date: {date_now}") - FAILS + # print(f"Date: {fake_date}") - FAILS # I already tested "04/01/2021 12:33:41" == fake_date: - # TRUE I don't understand why this is happening - print(f"Date: 04/01/2021 12:33:41") + # is "TRUE" I don't understand why even fake time is failing + # only hardcoded time passes + print("Date: 04/01/2021 12:33:41") print(f"Thanks, {customer.name}, for your purchase!") - print(f"You have bought:") + print("You have bought:") total_price_cart = 0 - for (_, value_need_customer), (product_name, product_price) in zip(customer.product_cart.items(), cheapest_shop[1].products.items()): + for ((_, value_need_customer), + (product_name, product_price)) in zip( + customer.product_cart.items(), + cheapest_shop[1].products.items() + ): total_amount_product = value_need_customer * product_price if total_amount_product == int(total_amount_product): total_amount_product = int(total_amount_product) total_price_cart += total_amount_product - print(f"{value_need_customer} {product_name}s for {total_amount_product} dollars") + print(f"{value_need_customer} {product_name}s " + f"for {total_amount_product} dollars") print(f"Total cost is {total_price_cart} dollars") - print(f"See you again!\n") + print("See you again!\n") print(f"{customer.name} rides home") print(f"{customer.name} now has " diff --git a/app/shop.py b/app/shop.py index b9e23338..45757219 100644 --- a/app/shop.py +++ b/app/shop.py @@ -11,7 +11,7 @@ def __init__(self, self.products = products -def load_shops_from_json(filepath): +def load_shops_from_json(filepath: str) -> list[Shop]: with open(filepath, "r") as file: data = json.load(file) shops_data = data.get("shops") @@ -19,6 +19,3 @@ def load_shops_from_json(filepath): shops_ = load_shops_from_json("app/config.json") - -# if "__main__" == __name__: -# load_shops_from_json("config.json") From a1d8e8168c6efe21cd3be7fd817223daf0090e7a Mon Sep 17 00:00:00 2001 From: kekW Date: Wed, 10 Apr 2024 21:18:16 +0300 Subject: [PATCH 3/6] fix after comments read --- app/car.py | 10 ------ app/customer.py | 12 ------- app/load_jsons.py | 7 ++++ app/main.py | 81 ++++++++++++++++------------------------------- app/shop.py | 48 ++++++++++++++++++++++++---- 5 files changed, 75 insertions(+), 83 deletions(-) create mode 100644 app/load_jsons.py diff --git a/app/car.py b/app/car.py index cb1fbcef..6cd6e9ca 100644 --- a/app/car.py +++ b/app/car.py @@ -1,4 +1,3 @@ -import json from dataclasses import dataclass @@ -6,12 +5,3 @@ class Car: brand: str = None fuel_consumption: float = None - - -def load_fuel_price_from_json(filepath: str) -> float: - with open(filepath, "r") as file: - data = json.load(file) - return data.get("FUEL_PRICE") - - -FUEL_PRICE = load_fuel_price_from_json("app/config.json") diff --git a/app/customer.py b/app/customer.py index a14d453a..43ea5126 100644 --- a/app/customer.py +++ b/app/customer.py @@ -1,5 +1,3 @@ -import json - from app.car import Car @@ -15,13 +13,3 @@ def __init__(self, self.location = location self.money = money self.car = Car(**car) - - -def load_customers_from_json(filepath: str) -> list[Customer]: - with open(filepath, "r") as file: - data = json.load(file) - customers_data = data.get("customers") - return [Customer(**customer_) for customer_ in customers_data] - - -customers_ = load_customers_from_json("app/config.json") diff --git a/app/load_jsons.py b/app/load_jsons.py new file mode 100644 index 00000000..5c9c8c4a --- /dev/null +++ b/app/load_jsons.py @@ -0,0 +1,7 @@ +import json + + +def load_complete_json(filepath: str) -> dict: + with open(filepath, "r") as file: + data = json.load(file) + return data diff --git a/app/main.py b/app/main.py index 9e25a435..0cbf49d8 100644 --- a/app/main.py +++ b/app/main.py @@ -1,82 +1,55 @@ -from math import sqrt +from collections import defaultdict -from app.car import FUEL_PRICE -from app.customer import customers_ -from app.shop import shops_ +from app.customer import Customer +from app.load_jsons import load_complete_json +from app.shop import Shop, shop_visit_price_calculation, checkout_for_products def shop_trip() -> None: - customers = customers_ - shops = shops_ - fuel_price = FUEL_PRICE + data = load_complete_json("app/config.json") + customers = [Customer(**customer_) for customer_ in data.get("customers")] + shops = [Shop(**shop) for shop in data.get("shops")] + fuel_price = data.get("FUEL_PRICE") for customer in customers: - cheapest_shop = [] + best_price_and_shop = defaultdict() print(f"{customer.name} has {customer.money} dollars") for shop in shops: - total_price = 0 - for (_, value_need_customer), (_, shop_item_price) in zip( - customer.product_cart.items(), shop.products.items() - ): - total_price += value_need_customer * shop_item_price - # our road distance is calculated hypotenuse, - # I'd argue about it, cars don't drive strait lines :) - one_way_distance = sqrt( - (customer.location[0] - shop.location[0]) ** 2 - + (customer.location[1] - shop.location[1]) ** 2 - ) - total_price += round(customer.car.fuel_consumption - * fuel_price / 100 * one_way_distance * 2, 2) - - # save every shop to chose from - cheapest_shop.append([total_price, shop]) + total_price_and_shop = shop_visit_price_calculation(customer, + shop, + fuel_price) print(f"{customer.name}'s trip to the {shop.name} " - f"costs {total_price}") + f"costs {total_price_and_shop['total_price']}") + + if (not best_price_and_shop or total_price_and_shop["total_price"] + < best_price_and_shop["total_price"]): + best_price_and_shop = total_price_and_shop - cheapest_shop = list(sorted(cheapest_shop)).pop(0) + best_shop_visit_price: float = best_price_and_shop["total_price"] + best_shop_instance: Shop = best_price_and_shop["shop"] - if customer.money >= cheapest_shop[0]: - print(f"{customer.name} rides to {cheapest_shop[1].name}\n") + if customer.money >= best_shop_visit_price: + print(f"{customer.name} rides to {best_shop_instance.name}\n") else: print(f"{customer.name} doesn't have enough " f"money to make a purchase in any shop") continue - # date_now = datetime.datetime.strftime(datetime.datetime.now(), - # "%d/%m/%Y %H:%M:%S") - # fake_date = datetime.datetime.strftime(datetime.datetime( - # 2021, 1, 4, 12, 33, 41 - # ), "%d/%m/%Y %H:%M:%S") - - # print(f"Date: 04/01/2021 12:33:41") - PASSES - # print(f"Date: {date_now}") - FAILS - # print(f"Date: {fake_date}") - FAILS - # I already tested "04/01/2021 12:33:41" == fake_date: - # is "TRUE" I don't understand why even fake time is failing - # only hardcoded time passes print("Date: 04/01/2021 12:33:41") print(f"Thanks, {customer.name}, for your purchase!") print("You have bought:") - total_price_cart = 0 + paper_check, cart_price = checkout_for_products(customer, + best_shop_instance) + for product_number_and_price in paper_check: + print(product_number_and_price) - for ((_, value_need_customer), - (product_name, product_price)) in zip( - customer.product_cart.items(), - cheapest_shop[1].products.items() - ): - total_amount_product = value_need_customer * product_price - if total_amount_product == int(total_amount_product): - total_amount_product = int(total_amount_product) - total_price_cart += total_amount_product - print(f"{value_need_customer} {product_name}s " - f"for {total_amount_product} dollars") - print(f"Total cost is {total_price_cart} dollars") + print(f"Total cost is {cart_price} dollars") print("See you again!\n") print(f"{customer.name} rides home") print(f"{customer.name} now has " - f"{customer.money - cheapest_shop[0]} dollars\n") + f"{customer.money - best_shop_visit_price} dollars\n") if "__main__" == __name__: diff --git a/app/shop.py b/app/shop.py index 45757219..a4c5a70c 100644 --- a/app/shop.py +++ b/app/shop.py @@ -1,4 +1,6 @@ -import json +from math import sqrt + +from app.customer import Customer class Shop: @@ -11,11 +13,43 @@ def __init__(self, self.products = products -def load_shops_from_json(filepath: str) -> list[Shop]: - with open(filepath, "r") as file: - data = json.load(file) - shops_data = data.get("shops") - return [Shop(**shop_) for shop_ in shops_data] +def shop_visit_price_calculation(customer: Customer, + shop: Shop, + fuel_price: float) -> dict: + total_price = 0 + for (_, value_need_customer), (_, shop_item_price) in zip( + customer.product_cart.items(), shop.products.items() + ): + total_price += value_need_customer * shop_item_price + + one_way_distance = sqrt( + (customer.location[0] - shop.location[0]) ** 2 + + (customer.location[1] - shop.location[1]) ** 2 + ) + total_price += round(customer.car.fuel_consumption + * fuel_price / 100 * one_way_distance * 2, 2) + + return {"total_price": total_price, + "shop": shop} + + +def checkout_for_products(customer: Customer, + shop_instance: Shop) -> tuple[list[str], float]: + total_cart_price = 0 + full_paper_check = [] + + for ((_, products_amount_customer_need), + (product_name, product_price)) in zip( + customer.product_cart.items(), + shop_instance.products.items() + ): + full_product_price = products_amount_customer_need * product_price + if full_product_price == int(full_product_price): + full_product_price = int(full_product_price) + total_cart_price += full_product_price + paper_check = (f"{products_amount_customer_need} {product_name}s " + f"for {full_product_price} dollars") + full_paper_check.append(paper_check) -shops_ = load_shops_from_json("app/config.json") + return full_paper_check, total_cart_price From 63a57ec13608d8800a94a51f6816e8a33d83cf3a Mon Sep 17 00:00:00 2001 From: kekW Date: Thu, 11 Apr 2024 23:17:41 +0300 Subject: [PATCH 4/6] moved most of code to methods, lots of rework --- app/customer.py | 60 +++++++++++++++++++++++++++++++++ app/main.py | 43 ++---------------------- app/shop.py | 89 +++++++++++++++++++++++++------------------------ 3 files changed, 108 insertions(+), 84 deletions(-) diff --git a/app/customer.py b/app/customer.py index 43ea5126..003639aa 100644 --- a/app/customer.py +++ b/app/customer.py @@ -1,4 +1,9 @@ +from collections import defaultdict +from math import sqrt + from app.car import Car +from app.shop import Cashier +from app.shop import Shop class Customer: @@ -13,3 +18,58 @@ def __init__(self, self.location = location self.money = money self.car = Car(**car) + + def choose_the_cheapest_shop_visit(self, + shops: list[Shop], + fuel_price: float) -> None: + best_price_and_shop = defaultdict() + print(f"{self.name} has {self.money} dollars") + + for shop in shops: + total_trip_price_shop = ( + Customer._shop_visit_price_calculation(self, shop, fuel_price) + ) + print(f"{self.name}'s trip to the {shop.name} " + f"costs {total_trip_price_shop['total_price']}") + + if ( + not best_price_and_shop + or total_trip_price_shop["total_price"] + < best_price_and_shop["total_price"] + ): + best_price_and_shop = total_trip_price_shop + + best_shop_visit_price: float = best_price_and_shop["total_price"] + best_shop_instance: Shop = best_price_and_shop["shop"] + + if self.money >= best_shop_visit_price: + print(f"{self.name} rides to {best_shop_instance.name}\n") + + Cashier.interaction_with_cashier(self, best_shop_instance) + self.ride_home(best_shop_visit_price) + else: + print(f"{self.name} doesn't have enough " + f"money to make a purchase in any shop") + + def _shop_visit_price_calculation(self, + shop: Shop, + fuel_price: float) -> dict: + total_price = 0 + for (_, value_need_customer), (_, shop_item_price) in zip( + self.product_cart.items(), shop.products.items() + ): + total_price += value_need_customer * shop_item_price + + one_way_distance = sqrt( + (self.location[0] - shop.location[0]) ** 2 + + (self.location[1] - shop.location[1]) ** 2 + ) + total_price += round(self.car.fuel_consumption + * fuel_price / 100 * one_way_distance * 2, 2) + + return {"total_price": total_price, + "shop": shop} + + def ride_home(self, best_shop_visit_price: float) -> None: + print(f"{self.name} rides home\n{self.name} now has " + f"{self.money - best_shop_visit_price} dollars\n") diff --git a/app/main.py b/app/main.py index 0cbf49d8..dcdbfccd 100644 --- a/app/main.py +++ b/app/main.py @@ -1,8 +1,6 @@ -from collections import defaultdict - from app.customer import Customer from app.load_jsons import load_complete_json -from app.shop import Shop, shop_visit_price_calculation, checkout_for_products +from app.shop import Shop def shop_trip() -> None: @@ -12,44 +10,7 @@ def shop_trip() -> None: fuel_price = data.get("FUEL_PRICE") for customer in customers: - best_price_and_shop = defaultdict() - print(f"{customer.name} has {customer.money} dollars") - for shop in shops: - total_price_and_shop = shop_visit_price_calculation(customer, - shop, - fuel_price) - print(f"{customer.name}'s trip to the {shop.name} " - f"costs {total_price_and_shop['total_price']}") - - if (not best_price_and_shop or total_price_and_shop["total_price"] - < best_price_and_shop["total_price"]): - best_price_and_shop = total_price_and_shop - - best_shop_visit_price: float = best_price_and_shop["total_price"] - best_shop_instance: Shop = best_price_and_shop["shop"] - - if customer.money >= best_shop_visit_price: - print(f"{customer.name} rides to {best_shop_instance.name}\n") - else: - print(f"{customer.name} doesn't have enough " - f"money to make a purchase in any shop") - continue - - print("Date: 04/01/2021 12:33:41") - print(f"Thanks, {customer.name}, for your purchase!") - print("You have bought:") - - paper_check, cart_price = checkout_for_products(customer, - best_shop_instance) - for product_number_and_price in paper_check: - print(product_number_and_price) - - print(f"Total cost is {cart_price} dollars") - print("See you again!\n") - - print(f"{customer.name} rides home") - print(f"{customer.name} now has " - f"{customer.money - best_shop_visit_price} dollars\n") + Customer.choose_the_cheapest_shop_visit(customer, shops, fuel_price) if "__main__" == __name__: diff --git a/app/shop.py b/app/shop.py index a4c5a70c..c50146b0 100644 --- a/app/shop.py +++ b/app/shop.py @@ -1,6 +1,8 @@ -from math import sqrt +import datetime +from typing import TYPE_CHECKING -from app.customer import Customer +if TYPE_CHECKING: + from app.customer import Customer class Shop: @@ -12,44 +14,45 @@ def __init__(self, self.location = location self.products = products - -def shop_visit_price_calculation(customer: Customer, - shop: Shop, - fuel_price: float) -> dict: - total_price = 0 - for (_, value_need_customer), (_, shop_item_price) in zip( - customer.product_cart.items(), shop.products.items() - ): - total_price += value_need_customer * shop_item_price - - one_way_distance = sqrt( - (customer.location[0] - shop.location[0]) ** 2 - + (customer.location[1] - shop.location[1]) ** 2 - ) - total_price += round(customer.car.fuel_consumption - * fuel_price / 100 * one_way_distance * 2, 2) - - return {"total_price": total_price, - "shop": shop} - - -def checkout_for_products(customer: Customer, - shop_instance: Shop) -> tuple[list[str], float]: - total_cart_price = 0 - full_paper_check = [] - - for ((_, products_amount_customer_need), - (product_name, product_price)) in zip( - customer.product_cart.items(), - shop_instance.products.items() - ): - full_product_price = products_amount_customer_need * product_price - if full_product_price == int(full_product_price): - full_product_price = int(full_product_price) - total_cart_price += full_product_price - - paper_check = (f"{products_amount_customer_need} {product_name}s " - f"for {full_product_price} dollars") - full_paper_check.append(paper_check) - - return full_paper_check, total_cart_price + def checkout_for_products( + self, + customer: "Customer" + ) -> tuple[list[str], float]: + + total_cart_price = 0 + full_paper_check = [] + + for ( + (_, products_amount_customer_need), + (product_name, product_price) + ) in zip(customer.product_cart.items(), self.products.items()): + full_product_price = products_amount_customer_need * product_price + if full_product_price == int(full_product_price): + full_product_price = int(full_product_price) + total_cart_price += full_product_price + + paper_check = (f"{products_amount_customer_need} {product_name}s " + f"for {full_product_price} dollars") + full_paper_check.append(paper_check) + + return full_paper_check, total_cart_price + + +class Cashier: + @staticmethod + def interaction_with_cashier( + customer: "Customer", + best_shop_instance: Shop + ) -> None: + str_date = datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S") + print(f"Date: {str_date}\n" + f"Thanks, {customer.name}, for your purchase!\n" + "You have bought:") + + paper_check, cart_price = Shop.checkout_for_products( + best_shop_instance, + customer) + for product_number_and_price in paper_check: + print(product_number_and_price) + + print(f"Total cost is {cart_price} dollars\nSee you again!\n") From d9af3b5a02e9b28105044e8032d0d16a705a6fbe Mon Sep 17 00:00:00 2001 From: kekW Date: Sat, 20 Apr 2024 20:36:00 +0300 Subject: [PATCH 5/6] lots of refactoring --- app/customer.py | 115 ++++++++++++++++++++++++++++++++---------------- app/main.py | 18 +++++--- app/shop.py | 50 --------------------- 3 files changed, 88 insertions(+), 95 deletions(-) diff --git a/app/customer.py b/app/customer.py index 003639aa..55c658d1 100644 --- a/app/customer.py +++ b/app/customer.py @@ -1,8 +1,7 @@ -from collections import defaultdict +import datetime from math import sqrt from app.car import Car -from app.shop import Cashier from app.shop import Shop @@ -19,57 +18,95 @@ def __init__(self, self.money = money self.car = Car(**car) - def choose_the_cheapest_shop_visit(self, - shops: list[Shop], - fuel_price: float) -> None: - best_price_and_shop = defaultdict() + def choose_the_cheapest_shop_visit( + self, + shops: list[Shop], + fuel_price: float + ) -> tuple: + print(f"{self.name} has {self.money} dollars") + best_price = best_shop = None for shop in shops: - total_trip_price_shop = ( - Customer._shop_visit_price_calculation(self, shop, fuel_price) - ) + total_trip_price_shop = self.money_spent_on_products(shop) + total_trip_price_shop += self.money_spent_on_fuel(shop, fuel_price) + print(f"{self.name}'s trip to the {shop.name} " - f"costs {total_trip_price_shop['total_price']}") + f"costs {total_trip_price_shop}") if ( - not best_price_and_shop - or total_trip_price_shop["total_price"] - < best_price_and_shop["total_price"] + not best_price + or total_trip_price_shop + < best_price ): - best_price_and_shop = total_trip_price_shop - - best_shop_visit_price: float = best_price_and_shop["total_price"] - best_shop_instance: Shop = best_price_and_shop["shop"] + best_price = total_trip_price_shop + best_shop = shop + return best_price, best_shop - if self.money >= best_shop_visit_price: - print(f"{self.name} rides to {best_shop_instance.name}\n") + def ride_home(self, best_shop_visit_price: float) -> None: + print(f"{self.name} rides home\n{self.name} now has " + f"{self.money - best_shop_visit_price} dollars\n") - Cashier.interaction_with_cashier(self, best_shop_instance) - self.ride_home(best_shop_visit_price) - else: - print(f"{self.name} doesn't have enough " - f"money to make a purchase in any shop") - - def _shop_visit_price_calculation(self, - shop: Shop, - fuel_price: float) -> dict: - total_price = 0 - for (_, value_need_customer), (_, shop_item_price) in zip( - self.product_cart.items(), shop.products.items() + def money_spent_on_products(self, shop: Shop) -> float: + total_products_price = 0 + for money_customer_need, shop_item_price in ( + zip(self.product_cart.values(), shop.products.values()) ): - total_price += value_need_customer * shop_item_price + total_products_price += money_customer_need * shop_item_price + return total_products_price + def money_spent_on_fuel(self, shop: Shop, fuel_price: float) -> float: one_way_distance = sqrt( (self.location[0] - shop.location[0]) ** 2 + (self.location[1] - shop.location[1]) ** 2 ) - total_price += round(self.car.fuel_consumption - * fuel_price / 100 * one_way_distance * 2, 2) + money_fuel_spent = round(self.car.fuel_consumption + * fuel_price / 100 * one_way_distance * 2, 2) + return money_fuel_spent - return {"total_price": total_price, - "shop": shop} + def calculate_if_enough_money( + self, + best_shop_visit_price: float, + best_shop_instance: Shop + ) -> bool: + if self.money >= best_shop_visit_price: + print(f"{self.name} rides to {best_shop_instance.name}\n") + return True - def ride_home(self, best_shop_visit_price: float) -> None: - print(f"{self.name} rides home\n{self.name} now has " - f"{self.money - best_shop_visit_price} dollars\n") + print(f"{self.name} doesn't have enough " + f"money to make a purchase in any shop") + return False + + def interaction_with_cashier(self, best_shop_instance: Shop) -> None: + str_date = datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S") + print(f"Date: {str_date}\n" + f"Thanks, {self.name}, for your purchase!\n" + "You have bought:") + + paper_check, cart_price = self._checkout_for_products( + shop=best_shop_instance + ) + + for products_amount_and_price in paper_check: + print(products_amount_and_price) + + print(f"Total cost is {cart_price} dollars\nSee you again!\n") + + def _checkout_for_products(self, shop: Shop) -> tuple[list[str], float]: + total_cart_price = 0 + full_paper_check = [] + + for products_amount_customer_need, (product_name, product_price) in ( + zip(self.product_cart.values(), shop.products.items()) + ): + full_product_price = products_amount_customer_need * product_price + # tests fail without it, they want rounded if it can be rounded + if full_product_price == int(full_product_price): + full_product_price = int(full_product_price) + total_cart_price += full_product_price + + paper_check = (f"{products_amount_customer_need} {product_name}s " + f"for {full_product_price} dollars") + full_paper_check.append(paper_check) + + return full_paper_check, total_cart_price diff --git a/app/main.py b/app/main.py index dcdbfccd..5a59562d 100644 --- a/app/main.py +++ b/app/main.py @@ -5,13 +5,19 @@ def shop_trip() -> None: data = load_complete_json("app/config.json") - customers = [Customer(**customer_) for customer_ in data.get("customers")] shops = [Shop(**shop) for shop in data.get("shops")] fuel_price = data.get("FUEL_PRICE") - for customer in customers: - Customer.choose_the_cheapest_shop_visit(customer, shops, fuel_price) + for customer_data in data.get("customers"): + customer = Customer(**customer_data) + best_price, best_shop = customer.choose_the_cheapest_shop_visit( + shops=shops, fuel_price=fuel_price + ) + is_enough_money = customer.calculate_if_enough_money( + best_shop_visit_price=best_price, best_shop_instance=best_shop + ) + if not is_enough_money: + continue - -if "__main__" == __name__: - shop_trip() + customer.interaction_with_cashier(best_shop_instance=best_shop) + customer.ride_home(best_shop_visit_price=best_price) diff --git a/app/shop.py b/app/shop.py index c50146b0..1be743d6 100644 --- a/app/shop.py +++ b/app/shop.py @@ -1,10 +1,3 @@ -import datetime -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from app.customer import Customer - - class Shop: def __init__(self, name: str, @@ -13,46 +6,3 @@ def __init__(self, self.name = name self.location = location self.products = products - - def checkout_for_products( - self, - customer: "Customer" - ) -> tuple[list[str], float]: - - total_cart_price = 0 - full_paper_check = [] - - for ( - (_, products_amount_customer_need), - (product_name, product_price) - ) in zip(customer.product_cart.items(), self.products.items()): - full_product_price = products_amount_customer_need * product_price - if full_product_price == int(full_product_price): - full_product_price = int(full_product_price) - total_cart_price += full_product_price - - paper_check = (f"{products_amount_customer_need} {product_name}s " - f"for {full_product_price} dollars") - full_paper_check.append(paper_check) - - return full_paper_check, total_cart_price - - -class Cashier: - @staticmethod - def interaction_with_cashier( - customer: "Customer", - best_shop_instance: Shop - ) -> None: - str_date = datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S") - print(f"Date: {str_date}\n" - f"Thanks, {customer.name}, for your purchase!\n" - "You have bought:") - - paper_check, cart_price = Shop.checkout_for_products( - best_shop_instance, - customer) - for product_number_and_price in paper_check: - print(product_number_and_price) - - print(f"Total cost is {cart_price} dollars\nSee you again!\n") From 1f0c89ff0016df8bfa6a4e9db26cda68566e5a2c Mon Sep 17 00:00:00 2001 From: kekW Date: Sat, 20 Apr 2024 20:49:27 +0300 Subject: [PATCH 6/6] changed Shop to dataclass since Shop doesn't have methods --- app/shop.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/shop.py b/app/shop.py index 1be743d6..51c9dce9 100644 --- a/app/shop.py +++ b/app/shop.py @@ -1,8 +1,8 @@ +from dataclasses import dataclass + + +@dataclass class Shop: - def __init__(self, - name: str, - location: list, - products: dict) -> None: - self.name = name - self.location = location - self.products = products + name: str = None + location: list[int] = None + products: dict[str:float] = None