mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-15 13:00:58 -04:00
fix(curriculum): use built-in list in workshop discount calculator (#66106)
This commit is contained in:
@@ -1,89 +0,0 @@
|
||||
---
|
||||
id: 68e52994bc7ea2e3dec530a0
|
||||
title: Step 23
|
||||
challengeType: 20
|
||||
dashedName: step-23
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now you need a way to manage multiple discount strategies and find the best price. At the top of your file, after the existing import, add an import for the `List` type from the `typing` module:
|
||||
|
||||
```py
|
||||
from typing import List
|
||||
```
|
||||
|
||||
This allows you to specify that a function parameter is a list containing specific types of objects.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should import `List` from the `typing` module as mentioned in the instructions after the existing imports.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`assert _Node(_code).find_imports()[1].is_equivalent("from typing import List")`)
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
from abc import ABC, abstractmethod
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
class Product:
|
||||
def __init__(self, name: str, price: float) -> None:
|
||||
self.name = name
|
||||
self.price = price
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f'{self.name} - ${self.price}'
|
||||
|
||||
class DiscountStrategy(ABC):
|
||||
@abstractmethod
|
||||
def is_applicable(self, product: Product, user_tier: str) -> bool:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def apply_discount(self, product: Product) -> float:
|
||||
pass
|
||||
|
||||
class PercentageDiscount(DiscountStrategy):
|
||||
def __init__(self, percent: int) -> None:
|
||||
self.percent = percent
|
||||
|
||||
def is_applicable(self, product: Product, user_tier: str) -> bool:
|
||||
return self.percent <= 70
|
||||
|
||||
def apply_discount(self, product: Product) -> float:
|
||||
return product.price * (1 - self.percent / 100)
|
||||
|
||||
class FixedAmountDiscount(DiscountStrategy):
|
||||
def __init__(self, amount: int) -> None:
|
||||
self.amount = amount
|
||||
|
||||
def is_applicable(self, product: Product, user_tier: str) -> bool:
|
||||
return product.price * 0.9 > self.amount
|
||||
|
||||
def apply_discount(self, product: Product) -> float:
|
||||
return product.price - self.amount
|
||||
|
||||
class PremiumUserDiscount(DiscountStrategy):
|
||||
def is_applicable(self, product: Product, user_tier: str) -> bool:
|
||||
return user_tier.lower() == 'premium'
|
||||
|
||||
def apply_discount(self, product: Product) -> float:
|
||||
return product.price * 0.8
|
||||
|
||||
product = Product('Wireless Mouse', 50.0)
|
||||
print(product)
|
||||
|
||||
discount = PercentageDiscount(10)
|
||||
print(discount.apply_discount(product))
|
||||
|
||||
fixed_discount = FixedAmountDiscount(5)
|
||||
print(fixed_discount.apply_discount(product))
|
||||
```
|
||||
@@ -1,15 +1,17 @@
|
||||
---
|
||||
id: 68e52994bc7ea2e3dec530a1
|
||||
title: Step 24
|
||||
title: Step 23
|
||||
challengeType: 20
|
||||
dashedName: step-24
|
||||
dashedName: step-23
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now you need a way to manage multiple discount strategies and find the best price.
|
||||
|
||||
Create a class named `DiscountEngine`. This class will manage all discount strategies and calculate the best price for a product.
|
||||
|
||||
Give it an `__init__` method that takes `self` and `strategies` as parameters, where `strategies` has a type hint of `List[DiscountStrategy]`. The return type of the method should be `None`. Inside the `__init__` method, store `strategies` as an instance attribute.
|
||||
Give it an `__init__` method that takes `self` and `strategies` as parameters, where `strategies` has a type hint of `list[DiscountStrategy]`. Using `list[DiscountStrategy]` specifies that the parameter is a list containing `DiscountStrategy` objects. The return type of the method should be `None`. Inside the `__init__` method, store `strategies` as an instance attribute.
|
||||
|
||||
# --hints--
|
||||
|
||||
@@ -29,11 +31,11 @@ Your `DiscountEngine` class should have an `__init__` method.
|
||||
})
|
||||
```
|
||||
|
||||
Your `__init__` method should have parameters `self` and `strategies: List[DiscountStrategy]`.
|
||||
Your `__init__` method should have parameters `self` and `strategies: list[DiscountStrategy]`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => runPython(`assert _Node(_code).find_class("DiscountEngine").find_function("__init__").has_args("self, strategies: List[DiscountStrategy]")`)
|
||||
test: () => runPython(`assert _Node(_code).find_class("DiscountEngine").find_function("__init__").has_args("self, strategies: list[DiscountStrategy]")`)
|
||||
})
|
||||
```
|
||||
|
||||
@@ -61,7 +63,6 @@ You should assign `strategies` to `self.strategies` inside your `__init__` metho
|
||||
|
||||
```py
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List
|
||||
|
||||
class Product:
|
||||
def __init__(self, name: str, price: float) -> None:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 68e52994bc7ea2e3dec530a2
|
||||
title: Step 25
|
||||
title: Step 24
|
||||
challengeType: 20
|
||||
dashedName: step-25
|
||||
dashedName: step-24
|
||||
---
|
||||
|
||||
# --description--
|
||||
@@ -43,7 +43,6 @@ Your `calculate_best_price` method should have a return type hint of `-> float`.
|
||||
|
||||
```py
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List
|
||||
|
||||
class Product:
|
||||
def __init__(self, name: str, price: float) -> None:
|
||||
@@ -90,7 +89,7 @@ class PremiumUserDiscount(DiscountStrategy):
|
||||
return product.price * 0.8
|
||||
|
||||
class DiscountEngine:
|
||||
def __init__(self, strategies: List[DiscountStrategy]) -> None:
|
||||
def __init__(self, strategies: list[DiscountStrategy]) -> None:
|
||||
self.strategies = strategies
|
||||
--fcc-editable-region--
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 68e52994bc7ea2e3dec530a3
|
||||
title: Step 26
|
||||
title: Step 25
|
||||
challengeType: 20
|
||||
dashedName: step-26
|
||||
dashedName: step-25
|
||||
---
|
||||
|
||||
# --description--
|
||||
@@ -25,7 +25,6 @@ Inside `calculate_best_price`, you should create a list named `prices` containin
|
||||
|
||||
```py
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List
|
||||
|
||||
class Product:
|
||||
def __init__(self, name: str, price: float) -> None:
|
||||
@@ -72,7 +71,7 @@ class PremiumUserDiscount(DiscountStrategy):
|
||||
return product.price * 0.8
|
||||
|
||||
class DiscountEngine:
|
||||
def __init__(self, strategies: List[DiscountStrategy]) -> None:
|
||||
def __init__(self, strategies: list[DiscountStrategy]) -> None:
|
||||
self.strategies = strategies
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 68e52994bc7ea2e3dec530a4
|
||||
title: Step 27
|
||||
title: Step 26
|
||||
challengeType: 20
|
||||
dashedName: step-27
|
||||
dashedName: step-26
|
||||
---
|
||||
|
||||
# --description--
|
||||
@@ -47,7 +47,6 @@ assert _Node(_code).find_class("DiscountEngine").find_function("calculate_best_p
|
||||
|
||||
```py
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List
|
||||
|
||||
class Product:
|
||||
def __init__(self, name: str, price: float) -> None:
|
||||
@@ -94,7 +93,7 @@ class PremiumUserDiscount(DiscountStrategy):
|
||||
return product.price * 0.8
|
||||
|
||||
class DiscountEngine:
|
||||
def __init__(self, strategies: List[DiscountStrategy]) -> None:
|
||||
def __init__(self, strategies: list[DiscountStrategy]) -> None:
|
||||
self.strategies = strategies
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 68e52994bc7ea2e3dec530a5
|
||||
title: Step 28
|
||||
title: Step 27
|
||||
challengeType: 20
|
||||
dashedName: step-28
|
||||
dashedName: step-27
|
||||
---
|
||||
|
||||
# --description--
|
||||
@@ -27,7 +27,6 @@ Your `calculate_best_price` method should return the minimum value from the `pri
|
||||
|
||||
```py
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List
|
||||
|
||||
class Product:
|
||||
def __init__(self, name: str, price: float) -> None:
|
||||
@@ -74,7 +73,7 @@ class PremiumUserDiscount(DiscountStrategy):
|
||||
return product.price * 0.8
|
||||
|
||||
class DiscountEngine:
|
||||
def __init__(self, strategies: List[DiscountStrategy]) -> None:
|
||||
def __init__(self, strategies: list[DiscountStrategy]) -> None:
|
||||
self.strategies = strategies
|
||||
|
||||
def calculate_best_price(self, product: Product, user_tier: str) -> float:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 68e52994bc7ea2e3dec530a6
|
||||
title: Step 30
|
||||
title: Step 29
|
||||
challengeType: 20
|
||||
dashedName: step-30
|
||||
dashedName: step-29
|
||||
---
|
||||
|
||||
# --description--
|
||||
@@ -51,7 +51,6 @@ You should create a list named `strategies` containing `PercentageDiscount(10)`,
|
||||
|
||||
```py
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List
|
||||
|
||||
class Product:
|
||||
def __init__(self, name: str, price: float) -> None:
|
||||
@@ -98,7 +97,7 @@ class PremiumUserDiscount(DiscountStrategy):
|
||||
return product.price * 0.8
|
||||
|
||||
class DiscountEngine:
|
||||
def __init__(self, strategies: List[DiscountStrategy]) -> None:
|
||||
def __init__(self, strategies: list[DiscountStrategy]) -> None:
|
||||
self.strategies = strategies
|
||||
|
||||
def calculate_best_price(self, product: Product, user_tier: str) -> float:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 68e52994bc7ea2e3dec530a7
|
||||
title: Step 32
|
||||
title: Step 31
|
||||
challengeType: 20
|
||||
dashedName: step-32
|
||||
dashedName: step-31
|
||||
---
|
||||
|
||||
# --description--
|
||||
@@ -41,7 +41,6 @@ Your output should match the format: `Best price for {product.name} for {user_ti
|
||||
|
||||
```py
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List
|
||||
|
||||
class Product:
|
||||
def __init__(self, name: str, price: float) -> None:
|
||||
@@ -88,7 +87,7 @@ class PremiumUserDiscount(DiscountStrategy):
|
||||
return product.price * 0.8
|
||||
|
||||
class DiscountEngine:
|
||||
def __init__(self, strategies: List[DiscountStrategy]) -> None:
|
||||
def __init__(self, strategies: list[DiscountStrategy]) -> None:
|
||||
self.strategies = strategies
|
||||
|
||||
def calculate_best_price(self, product: Product, user_tier: str) -> float:
|
||||
@@ -122,7 +121,6 @@ if __name__ == '__main__':
|
||||
|
||||
```py
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List
|
||||
|
||||
class Product:
|
||||
def __init__(self, name: str, price: float) -> None:
|
||||
@@ -168,7 +166,7 @@ class PremiumUserDiscount(DiscountStrategy):
|
||||
return product.price * 0.8 # 20% off for premium users
|
||||
|
||||
class DiscountEngine:
|
||||
def __init__(self, strategies: List[DiscountStrategy]) -> None:
|
||||
def __init__(self, strategies: list[DiscountStrategy]) -> None:
|
||||
self.strategies = strategies
|
||||
|
||||
def calculate_best_price(self, product: Product, user_tier: str) -> float:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 68e7a24b2482bd5fa88774fa
|
||||
title: Step 29
|
||||
title: Step 28
|
||||
challengeType: 20
|
||||
dashedName: step-29
|
||||
dashedName: step-28
|
||||
---
|
||||
|
||||
# --description--
|
||||
@@ -65,7 +65,6 @@ You should not have the line `print(fixed_discount.apply_discount(product))` in
|
||||
|
||||
```py
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List
|
||||
|
||||
class Product:
|
||||
def __init__(self, name: str, price: float) -> None:
|
||||
@@ -112,7 +111,7 @@ class PremiumUserDiscount(DiscountStrategy):
|
||||
return product.price * 0.8
|
||||
|
||||
class DiscountEngine:
|
||||
def __init__(self, strategies: List[DiscountStrategy]) -> None:
|
||||
def __init__(self, strategies: list[DiscountStrategy]) -> None:
|
||||
self.strategies = strategies
|
||||
|
||||
def calculate_best_price(self, product: Product, user_tier: str) -> float:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 68efb04d5ea87cf267192ed4
|
||||
title: Step 31
|
||||
title: Step 30
|
||||
challengeType: 20
|
||||
dashedName: step-31
|
||||
dashedName: step-30
|
||||
---
|
||||
|
||||
# --description--
|
||||
@@ -34,7 +34,6 @@ You should call `engine.calculate_best_price(product, user_tier)` and store the
|
||||
|
||||
```py
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List
|
||||
|
||||
class Product:
|
||||
def __init__(self, name: str, price: float) -> None:
|
||||
@@ -81,7 +80,7 @@ class PremiumUserDiscount(DiscountStrategy):
|
||||
return product.price * 0.8
|
||||
|
||||
class DiscountEngine:
|
||||
def __init__(self, strategies: List[DiscountStrategy]) -> None:
|
||||
def __init__(self, strategies: list[DiscountStrategy]) -> None:
|
||||
self.strategies = strategies
|
||||
|
||||
def calculate_best_price(self, product: Product, user_tier: str) -> float:
|
||||
|
||||
@@ -27,16 +27,15 @@
|
||||
{ "id": "68e52994bc7ea2e3dec5309d", "title": "Step 20" },
|
||||
{ "id": "68e52994bc7ea2e3dec5309e", "title": "Step 21" },
|
||||
{ "id": "68e52994bc7ea2e3dec5309f", "title": "Step 22" },
|
||||
{ "id": "68e52994bc7ea2e3dec530a0", "title": "Step 23" },
|
||||
{ "id": "68e52994bc7ea2e3dec530a1", "title": "Step 24" },
|
||||
{ "id": "68e52994bc7ea2e3dec530a2", "title": "Step 25" },
|
||||
{ "id": "68e52994bc7ea2e3dec530a3", "title": "Step 26" },
|
||||
{ "id": "68e52994bc7ea2e3dec530a4", "title": "Step 27" },
|
||||
{ "id": "68e52994bc7ea2e3dec530a5", "title": "Step 28" },
|
||||
{ "id": "68e7a24b2482bd5fa88774fa", "title": "Step 29" },
|
||||
{ "id": "68e52994bc7ea2e3dec530a6", "title": "Step 30" },
|
||||
{ "id": "68efb04d5ea87cf267192ed4", "title": "Step 31" },
|
||||
{ "id": "68e52994bc7ea2e3dec530a7", "title": "Step 32" }
|
||||
{ "id": "68e52994bc7ea2e3dec530a1", "title": "Step 23" },
|
||||
{ "id": "68e52994bc7ea2e3dec530a2", "title": "Step 24" },
|
||||
{ "id": "68e52994bc7ea2e3dec530a3", "title": "Step 25" },
|
||||
{ "id": "68e52994bc7ea2e3dec530a4", "title": "Step 26" },
|
||||
{ "id": "68e52994bc7ea2e3dec530a5", "title": "Step 27" },
|
||||
{ "id": "68e7a24b2482bd5fa88774fa", "title": "Step 28" },
|
||||
{ "id": "68e52994bc7ea2e3dec530a6", "title": "Step 29" },
|
||||
{ "id": "68efb04d5ea87cf267192ed4", "title": "Step 30" },
|
||||
{ "id": "68e52994bc7ea2e3dec530a7", "title": "Step 31" }
|
||||
],
|
||||
"blockLabel": "workshop",
|
||||
"usesMultifileEditor": true,
|
||||
|
||||
Reference in New Issue
Block a user