[O] Sort by price
This commit is contained in:
+28
-21
@@ -7,24 +7,37 @@ import time
|
|||||||
import traceback
|
import traceback
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict
|
|
||||||
|
|
||||||
import json5
|
import json5
|
||||||
import requests
|
import requests
|
||||||
import schedule as schedule
|
import schedule as schedule
|
||||||
import telegram
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from tabulate import tabulate
|
|
||||||
from telegram import Update
|
from telegram import Update
|
||||||
from telegram.ext import Updater, CallbackContext, Dispatcher, CommandHandler, MessageHandler, \
|
from telegram.ext import Updater, CallbackContext, Dispatcher, CommandHandler, MessageHandler, \
|
||||||
Filters
|
Filters
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MenuItem:
|
||||||
|
name: str
|
||||||
|
serving_size: str
|
||||||
|
price: float
|
||||||
|
calories: int
|
||||||
|
|
||||||
|
|
||||||
|
# menu_id_map[menu name] = menu id
|
||||||
|
MenuIdMap = dict[str, str]
|
||||||
|
# dining_halls[hall name][menu name] = menu id
|
||||||
|
DiningHalls = dict[str, MenuIdMap]
|
||||||
|
RawMenu = list[list[str]]
|
||||||
|
Menu = dict[str, list[MenuItem]]
|
||||||
|
|
||||||
|
|
||||||
def report(msg: str) -> None:
|
def report(msg: str) -> None:
|
||||||
print(msg)
|
print(msg)
|
||||||
|
|
||||||
|
|
||||||
def get_dining_halls() -> dict[str, dict[str, str]]:
|
def get_dining_halls() -> DiningHalls:
|
||||||
r: str = requests.get('https://fso.ueat.utoronto.ca/FSO/ServiceMenuReport/Today').text
|
r: str = requests.get('https://fso.ueat.utoronto.ca/FSO/ServiceMenuReport/Today').text
|
||||||
m: list[str] = re.findall(r"ASPx\.createControl\(MVCxClientMenu,'mnuUnits','',.*", r)
|
m: list[str] = re.findall(r"ASPx\.createControl\(MVCxClientMenu,'mnuUnits','',.*", r)
|
||||||
|
|
||||||
@@ -40,7 +53,7 @@ def get_dining_halls() -> dict[str, dict[str, str]]:
|
|||||||
items_json = re.findall(r"(?<={'items':).*(?=})", data)[0]
|
items_json = re.findall(r"(?<={'items':).*(?=})", data)[0]
|
||||||
items = json5.loads(items_json)[0]['items']
|
items = json5.loads(items_json)[0]['items']
|
||||||
|
|
||||||
dining_halls: dict[str, dict[str, str]] = {}
|
dining_halls: DiningHalls = {}
|
||||||
|
|
||||||
# Get dining hall names
|
# Get dining hall names
|
||||||
for i in items:
|
for i in items:
|
||||||
@@ -57,15 +70,7 @@ def get_dining_halls() -> dict[str, dict[str, str]]:
|
|||||||
return dining_halls
|
return dining_halls
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
def get_menu(id: str) -> tuple[RawMenu, Menu]:
|
||||||
class MenuItem:
|
|
||||||
name: str
|
|
||||||
serving_size: str
|
|
||||||
price: float
|
|
||||||
calories: int
|
|
||||||
|
|
||||||
|
|
||||||
def get_menu(id: str) -> tuple[list[list[str]], dict[str, list[MenuItem]]]:
|
|
||||||
r = requests.post(f" https://fso.ueat.utoronto.ca/FSO/ServiceMenuReport/GetReport/{id}").text
|
r = requests.post(f" https://fso.ueat.utoronto.ca/FSO/ServiceMenuReport/GetReport/{id}").text
|
||||||
s = BeautifulSoup(r, 'html.parser')
|
s = BeautifulSoup(r, 'html.parser')
|
||||||
|
|
||||||
@@ -87,8 +92,8 @@ def get_menu(id: str) -> tuple[list[list[str]], dict[str, list[MenuItem]]]:
|
|||||||
return d, data
|
return d, data
|
||||||
|
|
||||||
|
|
||||||
def filter_menu(menu: dict[str, list[MenuItem]]) -> dict[str, list[MenuItem]]:
|
def filter_menu(menu: Menu) -> Menu:
|
||||||
menu: dict[str, list[MenuItem]] = \
|
menu: Menu = \
|
||||||
{m: [i for i in menu[m] if i.price != -1] for m in menu}
|
{m: [i for i in menu[m] if i.price != -1] for m in menu}
|
||||||
|
|
||||||
for m in menu:
|
for m in menu:
|
||||||
@@ -148,15 +153,15 @@ if __name__ == '__main__':
|
|||||||
halls = get_dining_halls()
|
halls = get_dining_halls()
|
||||||
r(u, '*Available Dining Halls:* \n' + '\n'.join(halls.keys()) + '\n\nNext: /menus <hall>')
|
r(u, '*Available Dining Halls:* \n' + '\n'.join(halls.keys()) + '\n\nNext: /menus <hall>')
|
||||||
|
|
||||||
def get_hall_with_name(hall: str):
|
def get_hall_with_name(hall: str) -> tuple[str, MenuIdMap]:
|
||||||
hall = hall.lower()
|
hall = hall.lower()
|
||||||
halls = get_dining_halls()
|
halls = get_dining_halls()
|
||||||
h = [halls[h] for h in halls if h.lower().startswith(hall)]
|
h = [h for h in halls if h.lower().startswith(hall)]
|
||||||
if len(h) == 0:
|
if len(h) == 0:
|
||||||
raise AssertionError(f'No dining hall {hall} found.')
|
raise AssertionError(f'No dining hall {hall} found.')
|
||||||
return h, h[0]
|
return h[0], halls[h[0]]
|
||||||
|
|
||||||
def get_menu_with_name(hall: str, menu: str):
|
def get_menu_with_name(hall: str, menu: str) -> tuple[str, str, Menu]:
|
||||||
menu = menu.lower()
|
menu = menu.lower()
|
||||||
hall, h = get_hall_with_name(hall)
|
hall, h = get_hall_with_name(hall)
|
||||||
m = [m for m in h if m.lower().startswith(menu)]
|
m = [m for m in h if m.lower().startswith(menu)]
|
||||||
@@ -164,7 +169,7 @@ if __name__ == '__main__':
|
|||||||
raise AssertionError(f'No menu {menu} found in {hall}.')
|
raise AssertionError(f'No menu {menu} found in {hall}.')
|
||||||
return hall, m[0], get_menu(h[m[0]])[1]
|
return hall, m[0], get_menu(h[m[0]])[1]
|
||||||
|
|
||||||
def get_menu_cats(hall: str, menu: str, cats: list[str]):
|
def get_menu_cats(hall: str, menu: str, cats: list[str]) -> tuple[str, str, Menu]:
|
||||||
hall, menu, m = get_menu_with_name(hall, menu)
|
hall, menu, m = get_menu_with_name(hall, menu)
|
||||||
m = filter_menu(m)
|
m = filter_menu(m)
|
||||||
copy_cats = cats.copy()
|
copy_cats = cats.copy()
|
||||||
@@ -197,6 +202,8 @@ if __name__ == '__main__':
|
|||||||
hall, menu = args[:2]
|
hall, menu = args[:2]
|
||||||
cats = args[2:]
|
cats = args[2:]
|
||||||
hall, menu, m = get_menu_cats(hall, menu, cats)
|
hall, menu, m = get_menu_cats(hall, menu, cats)
|
||||||
|
for n in m:
|
||||||
|
m[n].sort(key=lambda x: -x.price)
|
||||||
msg = f"*Today's Menu for {menu}:* \n" + \
|
msg = f"*Today's Menu for {menu}:* \n" + \
|
||||||
'\n'.join(f"\n*{n}:* \n" + '\n'.join(
|
'\n'.join(f"\n*{n}:* \n" + '\n'.join(
|
||||||
f"{i + 1}. {m[n][i].name} - ${m[n][i].price}" for i in range(len(m[n])))
|
f"{i + 1}. {m[n][i].name} - ${m[n][i].price}" for i in range(len(m[n])))
|
||||||
|
|||||||
+13
-4
@@ -1,12 +1,21 @@
|
|||||||
# CSC110Y1F: Python libraries we'll be using this semester.
|
# CSC110Y1F: Python libraries we'll be using this semester.
|
||||||
|
|
||||||
# Testing and code checking
|
# Testing and code checking
|
||||||
hypothesis
|
hypothesis~=6.21.5
|
||||||
pytest
|
pytest~=6.2.5
|
||||||
python-ta
|
python-ta
|
||||||
|
|
||||||
# Graphics and data visualization
|
# Graphics and data visualization
|
||||||
plotly
|
plotly~=5.3.1
|
||||||
pygame
|
pygame
|
||||||
|
|
||||||
requests
|
requests~=2.21.0
|
||||||
|
|
||||||
|
json5~=0.9.6
|
||||||
|
schedule~=1.1.0
|
||||||
|
beautifulsoup4~=4.10.0
|
||||||
|
future~=0.18.2
|
||||||
|
Pillow~=8.2.0
|
||||||
|
numpy~=1.21.4
|
||||||
|
matplotlib~=3.5.1
|
||||||
|
tweepy~=4.4.0
|
||||||
|
|||||||
Reference in New Issue
Block a user