Reformat with black

This commit is contained in:
Midgard 2020-07-17 11:40:15 +02:00
parent 588ffdadfb
commit 4f7ffc0e3d
Signed by: midgard
GPG key ID: 511C112F1331BBB4
18 changed files with 204 additions and 131 deletions

View file

@ -92,8 +92,7 @@ def register_plugins(app: Flask) -> Manager:
# Make cookies more secure
app.config.update(
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE='Lax',
SESSION_COOKIE_HTTPONLY=True, SESSION_COOKIE_SAMESITE="Lax",
)
if not app.debug:
@ -140,8 +139,9 @@ def add_template_filters(app: Flask) -> None:
"Add functions which can be used in the templates"
# pylint: disable=W0612
@app.template_filter("countdown")
def countdown(value, only_positive: bool = True,
show_text: bool = True, reload: bool = True) -> str:
def countdown(
value, only_positive: bool = True, show_text: bool = True, reload: bool = True
) -> str:
delta = int(value.timestamp() - datetime.now().timestamp())
if delta < 0 and only_positive:
text = "closed"
@ -157,8 +157,11 @@ def add_template_filters(app: Flask) -> None:
reload_str = "yes" if reload else "no"
return Markup(f"<span class='time' data-seconds='{delta}' data-reload='{reload_str}'>" +
text + "</span>")
return Markup(
f"<span class='time' data-seconds='{delta}' data-reload='{reload_str}'>"
+ text
+ "</span>"
)
@app.template_filter("year")
def current_year(_value: typing.Any) -> str:

View file

@ -71,7 +71,7 @@ def add_to_current() -> None:
@app_manager.command
def setup_database(): #type: None
def setup_database(): # type: None
"Start the database interaction script"
print("Database modification script!")
print("=============================\n\n")

View file

@ -36,9 +36,9 @@ class FatOrder(Order, FatModel):
@classmethod
def items_per_order(cls):
return (
Order.query.join(OrderItem).group_by(Order.id)
.with_entities(Order.id,
func.count(OrderItem.user_id).label("total"))
Order.query.join(OrderItem)
.group_by(Order.id)
.with_entities(Order.id, func.count(OrderItem.user_id).label("total"))
)

View file

@ -6,8 +6,15 @@ from typing import Optional
from flask import session, request
from flask_login import current_user
from flask_wtf import FlaskForm as Form
from wtforms import (DateTimeField, SelectField, SelectMultipleField, StringField, SubmitField,
FieldList, validators)
from wtforms import (
DateTimeField,
SelectField,
SelectMultipleField,
StringField,
SubmitField,
FieldList,
validators,
)
from utils import euro_string, price_range_string
from hlds.definitions import location_definitions
@ -39,9 +46,7 @@ class OrderForm(Form):
(0, None),
(current_user.id, current_user.username),
]
self.location_id.choices = [
(l.id, l.name) for l in location_definitions
]
self.location_id.choices = [(l.id, l.name) for l in location_definitions]
if self.stoptime.data is None:
self.stoptime.data = datetime.now() + timedelta(hours=1)
@ -67,6 +72,7 @@ class AnonOrderItemForm(OrderItemForm):
Class which defines the form for a new Item in an Order
For Users who aren't logged in
"""
user_name = StringField("Name", validators=[validators.required()])
def populate(self, location: Location) -> None:

View file

@ -6,11 +6,9 @@ from utils import euro_string, first
def _format_tags(tags: Iterable[str]) -> str:
return (
" :: {}".format(" ".join(["{" + tag + "}" for tag in tags]))
if tags else
""
)
return " :: {}".format(" ".join(["{" + tag + "}" for tag in tags])) \
if tags \
else ""
def _format_price(price: int) -> str:
@ -35,7 +33,7 @@ class Option:
self,
" -- {}".format(self.description) if self.description else "",
_format_tags(self.tags),
_format_price(self.price)
_format_price(self.price),
)
@ -51,7 +49,7 @@ class Choice:
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))
"\n\t\t".join(map(str, self.options)),
)
def option_by_id(self, option_id: str) -> Optional[Option]:
@ -75,12 +73,14 @@ class Dish:
" -- {}".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))
"\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))
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(
@ -91,7 +91,9 @@ class Dish:
class Location:
def __init__(self, id_, *, name, dishes, osm=None, address=None, telephone=None, website=None):
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
@ -114,11 +116,15 @@ class Location:
"{2}"
).format(
self,
"".join("\n\t{} {}".format(k, v) for k, v in (
"".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))
)
if v is not None
),
"\n".join(map(str, self.dishes)),
)

View file

@ -24,7 +24,9 @@ def filter_instance(cls, iterable):
# pylint: disable=no-self-use
class HldsSemanticActions:
def location(self, ast) -> Location:
choices = {choice.id: choice for choice in filter_instance(Choice, ast["items_"])}
choices = {
choice.id: choice for choice in filter_instance(Choice, ast["items_"])
}
dishes: Iterable[Dish] = filter_instance(Dish, ast["items_"])
for dish in dishes:
for i, choice in enumerate(dish.choices):
@ -32,7 +34,9 @@ class HldsSemanticActions:
dish.choices[i] = (dish.choices[i][0], deepcopy(choices[choice[1]]))
# Move the base price to the first single_choice if the dish has a fixed price
first_single_choice = first(c[1] for c in dish.choices if c[0] == "single_choice")
first_single_choice = first(
c[1] for c in dish.choices if c[0] == "single_choice"
)
price_range = dish.price_range()
if dish.price and price_range[0] != price_range[1] and first_single_choice:
for option in first_single_choice.options:
@ -41,7 +45,6 @@ class HldsSemanticActions:
attributes = {att["key"]: att["value"] for att in ast["attributes"]}
return Location(
ast["id"],
name=ast["name"],
@ -64,7 +67,9 @@ class HldsSemanticActions:
def choice_block(self, ast) -> Choice:
if ast["price"] or ast["tags"]:
raise SemanticError("Choice blocks cannot have price or tags, put them on each of its options instead")
raise SemanticError(
"Choice blocks cannot have price or tags, put them on each of its options instead"
)
return Choice(
ast["id"],
@ -76,8 +81,8 @@ class HldsSemanticActions:
def indent_choice_block(self, ast) -> Tuple[str, Union[Choice, AST]]:
return (
(ast["type"], self.choice_block(ast))
if ast["kind"] == "declaration" else
(ast["type"], ast["id"])
if ast["kind"] == "declaration"
else (ast["type"], ast["id"])
)
def indent_choice_entry(self, ast) -> Option:
@ -92,18 +97,18 @@ class HldsSemanticActions:
noindent_choice_entry = indent_choice_entry
def price(self, ast) -> int:
return (
100 * int(ast["value_unit"]) +
(
0 if not ast["value_cents"] else
10 * int(ast["value_cents"]) if len(ast["value_cents"]) == 1 else
int(ast["value_cents"])
)
return 100 * int(ast["value_unit"]) + (
0
if not ast["value_cents"]
else 10 * int(ast["value_cents"])
if len(ast["value_cents"]) == 1
else int(ast["value_cents"])
)
def _default(self, ast):
return ast
SEMANTICS = HldsSemanticActions()

View file

@ -4,6 +4,7 @@ from __future__ import with_statement
from logging.config import fileConfig
from alembic import context
# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel

View file

@ -22,7 +22,9 @@ class Order(db.Model):
def __getattr__(self, name):
if name == "location":
return first(filter(lambda l: l.id == self.location_id, location_definitions))
return first(
filter(lambda l: l.id == self.location_id, location_definitions)
)
raise AttributeError()
def __repr__(self) -> str:
@ -37,7 +39,9 @@ class Order(db.Model):
Update the location name from the HLDS definition.
User should commit after running this to make the change persistent.
"""
assert self.location_id, "location_id must be configured before updating from HLDS"
assert (
self.location_id
), "location_id must be configured before updating from HLDS"
self.location_name = self.location.name
def group_by_user(self) -> typing.Dict[str, typing.Any]:
@ -46,17 +50,16 @@ class Order(db.Model):
for item in self.items:
user = group.get(item.get_name(), dict())
user["total"] = user.get("total", 0) + item.price
user["to_pay"] = (
user.get("to_pay", 0) +
item.price if not item.paid else 0
)
user["to_pay"] = user.get("to_pay", 0) + item.price if not item.paid else 0
user["paid"] = user.get("paid", True) and item.paid
user["dishes"] = user.get("dishes", []) + [item.dish_name]
group[str(item.get_name())] = user
return group
def group_by_dish(self, sort_comments=False) -> typing.Dict[str, typing.Dict[str, typing.Any]]:
def group_by_dish(
self, sort_comments=False
) -> typing.Dict[str, typing.Dict[str, typing.Any]]:
"Group items of an Order by dish"
group: typing.Dict[str, typing.Dict[str, typing.Any]] = dict()
for item in self.items:

View file

@ -17,9 +17,7 @@ class OrderItem(db.Model):
dish_id = db.Column(db.String(64), nullable=True)
dish_name = db.Column(db.String(120), nullable=True)
price = db.Column(db.Integer, nullable=True)
paid = db.Column(
db.Boolean, default=False, nullable=True
)
paid = db.Column(db.Boolean, default=False, nullable=True)
comment = db.Column(db.Text(), nullable=True)
hlds_data_version = db.Column(db.String(40), nullable=True)
@ -27,8 +25,12 @@ class OrderItem(db.Model):
def __getattr__(self, name):
if name == "dish":
location_id = Order.query.filter(Order.id == self.order_id).first().location_id
location = first(filter(lambda l: l.id == location_id, location_definitions))
location_id = (
Order.query.filter(Order.id == self.order_id).first().location_id
)
location = first(
filter(lambda l: l.id == location_id, location_definitions)
)
if location:
return first(filter(lambda d: d.id == self.dish_id, location.dishes))
else:

View file

@ -7,7 +7,9 @@ from .orderitem import OrderItem
class OrderItemChoice(db.Model):
id = db.Column(db.Integer, primary_key=True)
choice_id = db.Column(db.String(64), nullable=True)
order_item_id = db.Column(db.Integer, db.ForeignKey("order_item.id"), nullable=False)
order_item_id = db.Column(
db.Integer, db.ForeignKey("order_item.id"), nullable=False
)
kind = db.Column(db.String(1), nullable=False)
name = db.Column(db.String(120), nullable=True)
value = db.Column(db.String(120), nullable=True)

View file

@ -35,8 +35,7 @@ def post_order_to_webhook(order: Order) -> None:
"Function that sends the notification for the order"
message = webhook_text(order)
if message:
webhookthread = WebhookSenderThread(
message, app.config["SLACK_WEBHOOK"])
webhookthread = WebhookSenderThread(message, app.config["SLACK_WEBHOOK"])
webhookthread.start()

View file

@ -24,6 +24,7 @@ def main(filenames):
if __name__ == "__main__":
import sys
args = sys.argv[1:]
if "-h" in args or "--help" in args:
print(USAGE.format(sys.argv[0]), file=sys.stderr)

View file

@ -10,6 +10,7 @@ if sys.executable != INTERP:
sys.path.append(os.getcwd())
from app import create_app
application = create_app().app
# For running on the server with passenger etc

View file

@ -9,10 +9,13 @@ def euro_string(value: int) -> str:
"""
return "{}.{:02}".format(*divmod(value, 100))
def price_range_string(price_range, include_upper=False):
if price_range[0] == price_range[1]:
return euro_string(price_range[0])
return ("{}{}" if include_upper else "from {}").format(*map(euro_string, price_range))
return ("{}{}" if include_upper else "from {}").format(
*map(euro_string, price_range)
)
def first(iterable: Iterable, default=None):

View file

@ -16,6 +16,7 @@ from utils import first
from hlds.definitions import location_definitions
from hlds.models import Location
from models import Order
# import views
from views.order import get_orders
@ -43,7 +44,7 @@ def get_css_dict(css_path):
# Open the YAML file with all the themes.
path = os.path.join(app.root_path, "views/themes.yml")
with open(path, 'r') as stream:
with open(path, "r") as stream:
data = yaml.safe_load(stream)
# Build a dictionary from the YAML file with all the themes and their attributes.
themes = {}
@ -57,46 +58,46 @@ def get_css_dict(css_path):
# Check each theme in the dictionary and return the first one that is "correct"
for key, theme in themes.items():
if theme['type'] == 'static-date':
start_day, start_month = theme['start'].split('/')
start_date = datetime(year=current_year, day=int(
start_day), month=int(start_month))
if theme["type"] == "static-date":
start_day, start_month = theme["start"].split("/")
start_date = datetime(year=current_year, day=int(start_day), month=int(start_month))
end_day, end_month = theme['end'].split('/')
end_day, end_month = theme["end"].split("/")
if int(start_month) > int(end_month):
current_year += 1
end_date = datetime(
year=current_year, day=int(end_day), month=int(end_month))
end_date = datetime(year=current_year, day=int(end_day), month=int(end_month))
if start_date <= current_date <= end_date:
path = os.path.join(app.root_path, css_path, theme['file'])
path = os.path.join(app.root_path, css_path, theme["file"])
themes_dict[key] = path
themes_dict['darkmode'] = os.path.join(
app.root_path, "static/css/themes/lowPerformance/darkmode.css")
themes_dict['lightmode'] = os.path.join(
app.root_path, "static/css/themes/lowPerformance/lightmode.css")
themes_dict["darkmode"] = os.path.join(
app.root_path, "static/css/themes/lowPerformance/darkmode.css"
)
themes_dict["lightmode"] = os.path.join(
app.root_path, "static/css/themes/lowPerformance/lightmode.css"
)
return themes_dict
def css_list():
"Generate the list of names of all the currently available themes"
if request.cookies.get('performance', '') == 'highPerformance':
css_path = 'static/css/themes/highPerformance/'
if request.cookies.get("performance", "") == "highPerformance":
css_path = "static/css/themes/highPerformance/"
else:
css_path = 'static/css/themes/lowPerformance/'
css_path = "static/css/themes/lowPerformance/"
return list(get_css_dict(css_path).keys())
@general_bp.route("/css")
def css():
"Generate the css"
if request.cookies.get('performance', '') == 'highPerformance':
css_path = 'static/css/themes/highPerformance/'
if request.cookies.get("performance", "") == "highPerformance":
css_path = "static/css/themes/highPerformance/"
else:
css_path = 'static/css/themes/lowPerformance/'
css_path = "static/css/themes/lowPerformance/"
cookie_theme = request.cookies.get('theme', '')
cookie_theme = request.cookies.get("theme", "")
themes_dict = get_css_dict(css_path)
@ -108,7 +109,7 @@ def css():
f = open(path)
response = make_response(f.read())
response.headers['Content-Type'] = 'text/css'
response.headers["Content-Type"] = "text/css"
f.close()
return response
@ -136,7 +137,9 @@ def location(location_id) -> str:
@general_bp.route("/location/<location_id>/<dish_id>")
def location_dish(location_id, dish_id) -> str:
loc: Optional[Location] = first(filter(lambda l: l.id == location_id, location_definitions))
loc: Optional[Location] = first(
filter(lambda l: l.id == location_id, location_definitions)
)
if loc is None:
abort(404)
dish = loc.dish_by_id(dish_id)
@ -154,10 +157,10 @@ def location_dish(location_id, dish_id) -> str:
"name": o.name,
"description": o.description,
"price": o.price,
"tags": o.tags
"tags": o.tags,
}
for o in c[1].options
]
],
}
for c in dish.choices
])

View file

@ -4,9 +4,19 @@ import typing
from datetime import datetime
from werkzeug.wrappers import Response
# from flask import current_app as app
from flask import (Blueprint, abort, flash, redirect, render_template, request,
session, url_for, wrappers)
from flask import (
Blueprint,
abort,
flash,
redirect,
render_template,
request,
session,
url_for,
wrappers,
)
from flask_login import current_user, login_required
from forms import AnonOrderItemForm, OrderForm, OrderItemForm
@ -57,8 +67,7 @@ def order_from_id(order_id: int, form: OrderForm = None, dish_id=None) -> str:
flash("Please login to see this order.", "info")
abort(401)
if form is None:
form = AnonOrderItemForm() if current_user.is_anonymous() \
else OrderItemForm()
form = AnonOrderItemForm() if current_user.is_anonymous() else OrderItemForm()
if order.location:
form.populate(order.location)
if order.is_closed():
@ -68,8 +77,14 @@ def order_from_id(order_id: int, form: OrderForm = None, dish_id=None) -> str:
dish = order.location.dish_by_id(dish_id) if order.location else None
return render_template("order.html", order=order, form=form,
total_price=total_price, debts=debts, dish=dish)
return render_template(
"order.html",
order=order,
form=form,
total_price=total_price,
debts=debts,
dish=dish,
)
@order_bp.route("/<order_id>/items")
@ -90,8 +105,7 @@ def items_showcase(order_id: int) -> str:
def order_edit(order_id: int) -> typing.Union[str, Response]:
"Generate order edit view from id"
order = Order.query.filter(Order.id == order_id).first()
if current_user.id is not order.courier_id and \
not current_user.is_admin():
if current_user.id is not order.courier_id and not current_user.is_admin():
abort(401)
if order is None:
abort(404)
@ -102,8 +116,7 @@ def order_edit(order_id: int) -> typing.Union[str, Response]:
order.update_from_hlds()
db.session.commit()
return redirect(url_for("order_bp.order_from_id", order_id=order.id))
return render_template("order_edit.html", form=orderForm,
order_id=order_id)
return render_template("order_edit.html", form=orderForm, order_id=order_id)
@order_bp.route("/<order_id>/create", methods=["GET", "POST"])
@ -123,8 +136,7 @@ def order_item_create(order_id: int) -> typing.Any:
# If location doesn't exist any more, adding items is nonsensical
if not location:
abort(404)
form = AnonOrderItemForm() if current_user.is_anonymous() \
else OrderItemForm()
form = AnonOrderItemForm() if current_user.is_anonymous() else OrderItemForm()
dish_id = form.dish_id.data if form.is_submitted() else request.args.get("dish")
if dish_id and not location.dish_by_id(dish_id):
@ -142,8 +154,14 @@ def order_item_create(order_id: int) -> typing.Any:
chosen = [
(
choice.option_by_id(request.form.get("choice_" + choice.id))
if choice_type == "single_choice" else
list(ignore_none(request.form.getlist("choice_" + choice.id, type=choice.option_by_id)))
if choice_type == "single_choice"
else list(
ignore_none(
request.form.getlist(
"choice_" + choice.id, type=choice.option_by_id
)
)
)
)
for (choice_type, choice) in choices
]
@ -151,14 +169,22 @@ def order_item_create(order_id: int) -> typing.Any:
if dish_was_changed or not all_choices_present:
try:
user_name = form.user_name.data if form.user_name.validate(form) else None
user_name = (
form.user_name.data if form.user_name.validate(form) else None
)
except AttributeError:
user_name = None
comment = form.comment.data if form.comment.validate(form) else None
return redirect(url_for("order_bp.order_item_create",
order_id=order_id, dish=form.dish_id.data,
user_name=user_name, comment=comment))
return redirect(
url_for(
"order_bp.order_item_create",
order_id=order_id,
dish=form.dish_id.data,
user_name=user_name,
comment=comment,
)
)
# If the form was not submitted (GET request) or the form had errors: show form again
if not form.validate_on_submit():
@ -184,6 +210,7 @@ def order_item_create(order_id: int) -> typing.Any:
return option.name
except AttributeError:
return ", ".join(o.name for o in option if no_text_tag not in o.tags)
comments = list(ignore_none(_name(option) for option in chosen))
if item.comment:
comments.append("Comment: " + item.comment)
@ -198,6 +225,7 @@ def order_item_create(order_id: int) -> typing.Any:
return option.price or 0
except AttributeError:
return sum(o.price or 0 for o in option)
item.price += sum(_price(option) for option in chosen)
db.session.add(item)
@ -216,8 +244,7 @@ def item_paid(order_id: int, item_id: int) -> typing.Optional[Response]:
if item.order.courier_id == user_id or current_user.admin:
item.paid = True
db.session.commit()
flash("Paid %s by %s" % (item.dish_name, item.get_name()),
"success")
flash("Paid %s by %s" % (item.dish_name, item.get_name()), "success")
return redirect(url_for("order_bp.order_from_id", order_id=order_id))
abort(404)
@ -244,8 +271,7 @@ def items_user_paid(order_id: int, user_name: str) -> typing.Optional[Response]:
for item in items:
item.paid = True
db.session.commit()
flash("Paid %d items for %s" %
(len(items), item.get_name()), "success")
flash("Paid %d items for %s" % (len(items), item.get_name()), "success")
return redirect(url_for("order_bp.order_from_id", order_id=order_id))
abort(404)
@ -293,7 +319,9 @@ def close_order(order_id: int) -> typing.Optional[Response]:
order = Order.query.filter(Order.id == order_id).first()
if order is None:
abort(404)
if (current_user.id == order.courier_id or current_user.is_admin()) and not order.is_closed():
if (
current_user.id == order.courier_id or current_user.is_admin()
) and not order.is_closed():
order.stoptime = datetime.now()
if order.courier_id == 0 or order.courier_id is None:
courier = select_user(order.items)
@ -332,7 +360,8 @@ def get_orders(expression=None) -> typing.List[Order]:
order_list: typing.List[OrderForm] = []
if expression is None:
expression = (datetime.now() > Order.starttime) & (
Order.stoptime > datetime.now()
Order.stoptime
> datetime.now()
# pylint: disable=C0121
) | (Order.stoptime == None)
if not current_user.is_anonymous():
@ -340,5 +369,6 @@ def get_orders(expression=None) -> typing.List[Order]:
else:
order_list = Order.query.filter(
# pylint: disable=C0121
(expression & (Order.public == True))).all()
(expression & (Order.public == True))
).all()
return order_list

View file

@ -1,8 +1,7 @@
"Script containing everything specific to ZeusWPI"
import typing
from flask import (Blueprint, current_app, flash, redirect, request, session,
url_for)
from flask import Blueprint, current_app, flash, redirect, request, session, url_for
from flask_login import login_user
from flask_oauthlib.client import OAuth, OAuthException
from werkzeug.wrappers import Response

View file

@ -1,15 +1,19 @@
#!/usr/bin/env python3
print("""============================
print(
"""============================
s5: S5
osm https://www.openstreetmap.org/node/3752879366
address Krijgslaan 281, 9000 Gent
website https://www.ugent.be/student/nl/meer-dan-studeren/resto/restos/restocampussterre.htm
============================""")
============================"""
)
# Paste menu from https://www.ugent.be/student/nl/meer-dan-studeren/resto/broodjes/overzicht.htm
# here
MENU = [l.split("\t") for l in """
MENU = [
l.split("\t")
for l in """
Spring break Erwten-munt spread, komkommer, radijs, sla, croutons, cocktailsaus 1,50 2,40
Groentespread Weekelijks wisselende groentespread 1,60 2,60
Brie Brie, honing, pijnboompitten, sla 1,50 2,50
@ -30,40 +34,44 @@ Maison Ham, kaas, augurk, ei, sla, tomaat, cocktailsaus en mayonaise € 1,60
Tropical Ham, kaas, ananas, ei, sla, cocktailsaus 1,60 2,40
Toscane Mozzarella, prosciutto ham, sla en tomatensalsa 1,60 2,70
Argenteuil Ham, asperge, ei, komkommer, sla, tomaat en mayonaise 1,50 2,40
""".strip().split("\n")]
""".strip().split(
"\n"
)
]
# Sort by price. This fails if price is not always exactly "€ x,xx" but whatever
MENU.sort(key=lambda dish: dish[2] + dish[3])
SANDWICHES = [
[ # First price
("small_white", "Klein wit "),
("small_brown", "Klein bruin"),
],
[("small_white", "Klein wit "), ("small_brown", "Klein bruin"),], # First price
[ # Second price
("large_white", "Groot wit "),
("large_brown", "Groot bruin"),
("quattro", " Quattro "),
]
],
]
def name_to_id(name):
return "".join(filter(
lambda c: ord("a") <= ord(c) <= ord("z"),
name.lower().replace("é", "e")
))
return "".join(
filter(lambda c: ord("a") <= ord(c) <= ord("z"), name.lower().replace("é", "e"))
)
for dish in MENU:
print()
name, description = dish[0], dish[1]
prices = [p.replace(",", ".") for p in dish[2:]]
print("dish sandwich_{}: Broodje {} -- {}".format(name_to_id(name), name, description))
print(
"dish sandwich_{}: Broodje {} -- {}".format(name_to_id(name), name, description)
)
print("\tsingle_choice sandwich: Broodje")
for sandwiches, price in zip(SANDWICHES, prices):
for sw_id, sw_name in sandwiches:
print("\t\t{}: {} {}".format(sw_id, sw_name, price))
print("""
print(
"""
dish yoghurt: Natuuryoghurt 0.4
dish yofu: Plantaardige yofu 1
dish yoghurt_muesli: Yoghurt met muesli 1
@ -86,4 +94,5 @@ dish bionade: Bionade € 1.5
dish finley: Finley 1
dish iced_coffee: IJskoffie 2
dish iced_tea: IJsthee 2
dish smoothie: Smoothie 2""")
dish smoothie: Smoothie 2"""
)