diff --git a/db/ddl.sql b/db/ddl.sql index d38a249..d9d283f 100644 --- a/db/ddl.sql +++ b/db/ddl.sql @@ -16,23 +16,16 @@ create table main.roll_result value text ); -create table main.sqlite_master -( - type TEXT, - name TEXT, - tbl_name TEXT, - rootpage INT, - sql TEXT -); - create table main.user_menu ( user text, menu text, datestr text, nickname text, - primary key (user, datestr), + dislike text, constraint user_menu_pk + primary key (user, datestr), + constraint user_menu_uk unique (nickname, datestr) ); diff --git a/src/dao.py b/src/dao.py index c3f8ac2..5b90ec0 100644 --- a/src/dao.py +++ b/src/dao.py @@ -46,6 +46,7 @@ def set_user_menu(menu: dict[str, float], nickname: str, dislike: list[str] = No 设置用户投票内容 :param menu: 投票内容 :param nickname: 姓名 + :param dislike: 不吃的清单 :param user: 用户,默认当前用户 """ datestr = datetime.now().strftime('%Y-%m-%d') diff --git a/src/dinner.py b/src/dinner.py index e4d883e..c349031 100644 --- a/src/dinner.py +++ b/src/dinner.py @@ -1,3 +1,4 @@ +from collections import defaultdict from itertools import chain from session import app @@ -7,7 +8,7 @@ from dao import * from utils import is_mobile_request -def fetch_user_menu_summary() -> tuple[dict[str, float], list[str], list[tuple[str, list[str]]]]: +def fetch_user_menu_summary() -> tuple[defaultdict[str, float], list[str], list[tuple[str, list[str]]]]: """ 获取今天所有人的投票汇总 :return: 品类->数量 @@ -17,15 +18,12 @@ def fetch_user_menu_summary() -> tuple[dict[str, float], list[str], list[tuple[s menus = list(map(lambda x: x.menu, all_menu)) users = list(map(lambda x: x.nickname, all_menu)) dislikes = list(map(lambda x: (x.nickname, x.dislike), all_menu)) - menu_keys = set(chain(*menus)) - result = {} - for k in menu_keys: - result[k] = 0 + result = defaultdict(float) for user_menu in menus: for k in user_menu: result[k] += user_menu[k] return result, users, dislikes - return {}, [], [] + return defaultdict(float), [], [] def within_time() -> bool: @@ -51,9 +49,9 @@ def check_roll() -> int: return 0 if within_time() else 1 -def vote_reduce(summary: dict[str, float], +def vote_reduce(summary: defaultdict[str, float], dislikes: list[tuple[str, list[str]]], limit: int = 2 - ) -> tuple[dict[str, float], float, list[RollResult]]: + ) -> tuple[defaultdict[str, float], int, list[RollResult]]: """ 按规则对投票结果进行修饰 :param summary: 投票汇总结果 @@ -62,7 +60,7 @@ def vote_reduce(summary: dict[str, float], :return: 投票汇总结果 """ last_results: list[RollResult] = list(fetch_roll_result_list(-1, limit)) - total_vote = sum(value for value in summary.values()) + total_vote = round(sum(value for value in summary.values())) menus: list[Menu] = list(fetch_all_menu()) for menu in menus: if menu.expression is None or menu.name not in summary.keys(): @@ -72,16 +70,12 @@ def vote_reduce(summary: dict[str, float], new_name = eval(menu.expression, {'total_vote': total_vote - dislike_cnt}) if new_name != menu.name: if new_name is not None: - if summary.get(new_name) is None: - summary[new_name] = summary[menu.name] - else: - summary[new_name] += summary[menu.name] + summary[new_name] += summary[menu.name] summary[menu.name] = 0 # 昨日中签项降低权重 for i, last_result in enumerate(last_results): if last_result.value in summary: summary[last_result.value] = summary[last_result.value] * (8 - i) / 10 - total_vote = sum(value for value in summary.values()) return summary, total_vote, last_results @@ -107,18 +101,16 @@ def dinner_update(): set_user_menu({}, nickname, []) return make_response(json.dumps(dict(code=0, data="OK"))) user_menu = json.loads(user_menu) - choice = user_menu['choice'] - dislike = user_menu.get('dislike') - if dislike is None: - dislike = [] + choice = {key: int(value) for key, value in user_menu['choice'].items() if int(value) > 0} + dislike = user_menu.get('dislike') or [] # 计算总投票数值 - summary = sum(abs(int(value)) for value in choice.values()) - if summary <= 0: + vote_sum = sum(value for value in choice.values()) + if vote_sum <= 0: set_user_menu({}, nickname, dislike) return make_response(json.dumps(dict(code=0, data="OK"))) # 投票数归一化 for key in choice: - choice[key] = abs(int(choice[key])) / summary + choice[key] /= vote_sum set_user_menu(choice, nickname, dislike) return make_response(json.dumps(dict(code=0, data="OK"))) @@ -154,6 +146,16 @@ def roll_logic(check=False): return None +def compute_eat_users(dislikes, result, users): + if result is None: + return [] + eat_users = users.copy() + for (n, d) in dislikes: + if result in d: + eat_users.remove(n) + return eat_users + + @app.route('/dinner') def dinner(): """ @@ -169,13 +171,9 @@ def dinner(): summary_keys = list(filter(lambda x: x in summary.keys(), map(lambda y: y.name, all_choice))) if not result: predict_result = roll_logic(check=True) - eat_users = [] else: - eat_users = users.copy() - for (n, d) in dislikes: - if result in d: - eat_users.remove(n) predict_result = None + eat_users = compute_eat_users(dislikes, result or predict_result, users) recent_results = list(fetch_roll_result_list(-1, 7)) return render_template('dinner.html', all_choice=all_choice, diff --git a/templates/dinner.html b/templates/dinner.html index 37dfaf5..ee52c65 100644 --- a/templates/dinner.html +++ b/templates/dinner.html @@ -22,9 +22,7 @@