diff options
Diffstat (limited to 'sjdbmk/menuparser.py')
-rw-r--r-- | sjdbmk/menuparser.py | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/sjdbmk/menuparser.py b/sjdbmk/menuparser.py new file mode 100644 index 0000000..7413ff0 --- /dev/null +++ b/sjdbmk/menuparser.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +# +# Utility functions to parse the XLSX menu for the Daily Bulletin +# Copyright (C) 2024 Runxi Yu <https://runxiyu.org> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# + + +from typing import Optional, Any + +import openpyxl + + +def menu_item_fix(s: str) -> Optional[str]: + if not s: + return None + if s == "Condiments Selection\n葱,香菜,榨菜丝,老干妈,生抽,醋": + return None + return ( + s.strip() + .replace("Biscuit /", "Biscuit/") + .replace("Juice /", "Juice/") + .replace(" \n", "\n") + .replace("\n ", "\n") + ) + + +def parse_meal_table( + rows: list[Any], initrow: int, t: list[str] +) -> dict[str, dict[str, list[str]]]: + assert rows[initrow + 1][1].value is None + + igroups = [] + i = initrow + 2 + while True: + c = rows[i][1] + if not isinstance(c, openpyxl.cell.MergedCell): + igroups.append(i) + i += 1 + if len(igroups) >= len(t): + break + wgroups = dict(zip(igroups + [i], t + [None])) + + ret: dict[str, dict[str, list[str]]] = {} + kmap = {} + for k in range(2, 7): + ret[rows[initrow + 1][k].value[0:3]] = {} + kmap[k] = rows[initrow + 1][k].value[0:3] + + i = 0 + wgroupskeys = list(wgroups.keys()) + while i < len(wgroupskeys) - 1: + wgroup = wgroups[wgroupskeys[i]] + assert wgroup is not None + for km in ret: + ret[km][wgroup] = [] + for j in range(wgroupskeys[i], wgroupskeys[i + 1]): + for k in range(2, 7): + v = menu_item_fix(rows[j][k].value) + if v: + ret[kmap[k]][wgroup].append(v) + i += 1 + + return ret + + +def parse_menus(filename: str) -> dict[str, dict[str, dict[str, list[str]]]]: + wb = openpyxl.load_workbook(filename=filename) + ws = wb["菜单"] + rows = list(ws.iter_rows()) + + final = {} + + i = -1 + while i < len(rows) - 1: + i += 1 + row = rows[i] + if not isinstance(row[1].value, str): + continue + if "BREAKFAST" in row[1].value: + final["Breakfast"] = parse_meal_table( + rows, + i, + [ + "Taste of Asia", + "Eat Global", + "Revolution Noodle", + "Piccola Italia", + "Self Pick-up", # instead of veg and soup + "Fruit/Drink", + ], + ) + elif "LUNCH" in row[1].value: + final["Lunch"] = parse_meal_table( + rows, + i, + [ + "Taste of Asia", + "Eat Global", + "Revolution Noodle", + "Piccola Italia", + "Vegetarian", + "Daily Soup", + "Dessert/Fruit/Drink", + ], + ) + elif "DINNER" in row[1].value: + final["Dinner"] = parse_meal_table( + rows, + i, + [ + "Taste of Asia", + "Eat Global", + "Revolution Noodle", + "Piccola Italia", + "Vegetarian", + "Daily Soup", + "Dessert/Fruit/Drink", + ], + ) + # elif "Students Snack" in row[1].value: + # parse_meal_table(rows, i) + + return final |