"""Here is a dictionary of supported currencies defined. Which could be easily extended with new ones. Each dictionary entry has an ISO code of a currency as its key. Or it can slightly differ from an ISO to represent a modified version of a currency. An example is SRUB entry for shortened version of RUB where coins of 1 and 5 kopek value were removed. And value is an another dictionary consists of following fields: name -- a full name of a currency; description -- usually a country where this currency is used is being mentioned. Plus additional information; count -- a number of coins in a currency; names -- an array of names for each coins' face values; multipliers -- an array of multipliers for each face value in a decimal format. Decimal is used to avoid problems of rounding float numbers. So first two digits are used to store a fraction part. You can simply divide this number by 100 to get a regular floating-point number. """ from typing import Dict, List, TypedDict __all__ = ["CURRENCIES", "DEFAULT_CURRENCY", "BaseCurrencyError", "CurrencyIsNotSupportedError", "CurrenciesCoinCountMismatchError", "CurrencyMismatchError", "print_supported_currencies"] class BaseCurrencyError(Exception): """Base class for all currency exeptions.""" def __init__(self, message=None, *args, **kwargs) -> None: if message is None: message = self.__doc__ super().__init__(message, *args, **kwargs) class CurrencyIsNotSupportedError(BaseCurrencyError): """Currency is not supported.""" pass class CurrencyMismatchError(BaseCurrencyError): """Currencies doesn't match, but they must do so.""" def __init__(self, extra=None): if not extra is None: super().__init__(f"{self.__doc__} {extra}") else: super().__init__(self.__doc__) class CurrenciesCoinCountMismatchError(BaseCurrencyError): """Count of coins of a new currency and an old one should be equal.""" pass DEFAULT_CURRENCY: str = "SRUB" class Currency(TypedDict): name: str description: str count: int names: List[str] multipliers: List[int] CURRENCIES: Dict[str, Currency] = { "RUB": { "name": "Ruble", "description": "Russian Federation", "count": 8, "names": ["1к.", "5к.", "10к.", "50к.", "1₽", "2₽", "5₽", "10₽"], "multipliers": [1, 5, 10, 50, 1_00, 2_00, 5_00, 10_00] }, "SRUB": { "name": "Ruble (shortened)", "description": "Russian Federation. Excluding coins of 1 and 5 kopek", "count": 6, "names": ["10к.", "50к.", "1₽", "2₽", "5₽", "10₽"], "multipliers": [10, 50, 1_00, 2_00, 5_00, 10_00] }, "BYN": { "name": "Belarusian ruble", "description": "Belarus", "count": 8, "names": ["1к.", "2к.", "5к.", "10к.", "20к.", "50к.", "1р.", "2р."], "multipliers": [1, 2, 5, 10, 20, 50, 1_00, 2_00] }, "UAH": { "name": "Ukrainian hryvnia", "description": "Ukraine", "count": 10, "names": ["1к.", "2к.", "5к.", "10к.", "25к.", "50к.", "₴1", "₴2", "₴5", "₴10"], "multipliers": [1, 2, 5, 10, 25, 50, 1_00, 2_00, 5_00, 10_00] }, "USD": { "name": "Dollar", "description": "United States of America", "count": 6, "names": ["1¢", "5¢", "10¢", "25¢", "50¢", "$1"], "multipliers": [1, 5, 10, 25, 50, 1_00] }, "EUR": { "name": "Euro", "description": "European Union", "count": 8, "names": ["1c", "2c", "5c", "10c", "20c", "50c", "€1", "€2"], "multipliers": [1, 2, 5, 10, 20, 50, 1_00, 2_00] }, "GBP": { "name": "Pound sterling", "description": "United Kingdom", "count": 9, "names": ["1p", "2p", "5p", "10p", "20p", "25p", "50p", "£1", "£2"], "multipliers": [1, 2, 5, 10, 20, 25, 50, 1_00, 2_00] } } def print_supported_currencies() -> None: """Print a list of supported currencies.""" print("Supported currencies are:") for cur in CURRENCIES: print(f" {cur:^4} ┃ {CURRENCIES[cur]['name']:^31}" f"┃ {CURRENCIES[cur]['description']}") print("Default currency is", DEFAULT_CURRENCY)