130 lines
3.9 KiB
Python
130 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
# pylint: disable=too-few-public-methods
|
|
|
|
from typing import Iterable, List, Tuple, Mapping, Any, Optional
|
|
from utils import euro_string, first
|
|
|
|
|
|
def _format_tags(tags: Iterable[str]) -> str:
|
|
return " :: {}".format(" ".join(["{" + tag + "}" for tag in tags])) \
|
|
if tags \
|
|
else ""
|
|
|
|
|
|
def _format_price(price: int) -> str:
|
|
return " {}".format(euro_string(price)) if price else ""
|
|
|
|
|
|
def _format_type_and_choice(type_and_choice):
|
|
type_, choice = type_and_choice
|
|
return "{} {}".format(type_, choice)
|
|
|
|
|
|
class Option:
|
|
def __init__(self, id_, *, name, description, price, tags):
|
|
self.id: str = id_
|
|
self.name: str = name
|
|
self.description: str = description
|
|
self.price: int = price
|
|
self.tags: List[str] = tags
|
|
|
|
def __str__(self):
|
|
return "{0.id}: {0.name}{1}{2}{3}".format(
|
|
self,
|
|
" -- {}".format(self.description) if self.description else "",
|
|
_format_tags(self.tags),
|
|
_format_price(self.price),
|
|
)
|
|
|
|
|
|
class Choice:
|
|
def __init__(self, id_, *, name, description, options):
|
|
self.id: str = id_
|
|
self.name: str = name
|
|
self.description: str = description
|
|
|
|
self.options: List[Option] = options
|
|
|
|
def __str__(self):
|
|
return "{0.id}: {0.name}{1}\n\t\t{2}".format(
|
|
self,
|
|
" -- {}".format(self.description) if self.description else "",
|
|
"\n\t\t".join(map(str, self.options)),
|
|
)
|
|
|
|
def option_by_id(self, option_id: str) -> Optional[Option]:
|
|
return first(filter(lambda o: o.id == option_id, self.options))
|
|
|
|
|
|
class Dish:
|
|
def __init__(self, id_, *, name, description, price, tags, choices):
|
|
self.id: str = id_
|
|
self.name: str = name
|
|
self.description: str = description
|
|
self.price: int = price
|
|
self.tags: List[str] = tags
|
|
|
|
# The str in (str, Choice) is the type of choice: single_choice or multi_choice
|
|
self.choices: List[(str, Choice)] = choices
|
|
|
|
def __str__(self):
|
|
return "dish {0.id}: {0.name}{1}{2}{3}\n\t{4}".format(
|
|
self,
|
|
" -- {}".format(self.description) if self.description else "",
|
|
_format_tags(self.tags),
|
|
_format_price(self.price),
|
|
"\n\t".join(map(_format_type_and_choice, self.choices)),
|
|
)
|
|
|
|
def price_range(self) -> Tuple[int, int]:
|
|
return (
|
|
self.price + self._sum_f_option_prices(min),
|
|
self.price + self._sum_f_option_prices(max),
|
|
)
|
|
|
|
def _sum_f_option_prices(self, f):
|
|
return sum(
|
|
f(option.price for option in choice.options)
|
|
for (choice_type, choice) in self.choices
|
|
if choice_type == "single_choice"
|
|
)
|
|
|
|
|
|
class Location:
|
|
def __init__(
|
|
self, id_, *, name, dishes, osm=None, address=None, telephone=None, website=None
|
|
):
|
|
self.id: str = id_
|
|
self.name: str = name
|
|
self.osm: Optional[str] = osm
|
|
self.address: Optional[str] = address
|
|
self.telephone: Optional[str] = telephone
|
|
self.website: Optional[str] = website
|
|
|
|
self.dishes: List[Dish] = dishes
|
|
|
|
def dish_by_id(self, dish_id: str) -> Optional[Dish]:
|
|
return first(filter(lambda d: d.id == dish_id, self.dishes))
|
|
|
|
def __str__(self):
|
|
return (
|
|
"============================\n"
|
|
"{0.id}: {0.name}"
|
|
"{1}\n"
|
|
"============================\n"
|
|
"\n"
|
|
"{2}"
|
|
).format(
|
|
self,
|
|
"".join(
|
|
"\n\t{} {}".format(k, v)
|
|
for k, v in (
|
|
("osm", self.osm),
|
|
("address", self.address),
|
|
("telephone", self.telephone),
|
|
("website", self.website),
|
|
)
|
|
if v is not None
|
|
),
|
|
"\n".join(map(str, self.dishes)),
|
|
)
|