2019-12-25 23:08:20 +04:00
|
|
|
|
"""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.
|
|
|
|
|
"""
|
|
|
|
|
|
2019-12-26 00:00:59 +04:00
|
|
|
|
from typing import Dict, List, TypedDict
|
2019-12-25 23:08:20 +04:00
|
|
|
|
|
|
|
|
|
__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"
|
|
|
|
|
|
2019-12-26 00:00:59 +04:00
|
|
|
|
|
|
|
|
|
class Currency(TypedDict):
|
|
|
|
|
name: str
|
|
|
|
|
description: str
|
|
|
|
|
count: int
|
|
|
|
|
names: List[str]
|
|
|
|
|
multipliers: List[int]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CURRENCIES: Dict[str, Currency] = {
|
2019-12-25 23:08:20 +04:00
|
|
|
|
"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)
|