import json from re import Pattern from session import app from flask import render_template, make_response, abort import re import random from dao import * MOBILE_AGENTS_PATTERN: Pattern[str] = re.compile( r"(android|bb\d+|meego).+mobile|avantgo|bada/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|" r"ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)/|plucker|" r"pocket|psp|series([46])0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino", re.IGNORECASE, ) def is_mobile_request(user_agent: str) -> bool: """ 判断是否是移动端 :param user_agent: UA :return: 是否 """ return bool(MOBILE_AGENTS_PATTERN.search(user_agent)) def fetch_user_menu_summary() -> dict[str, float]: """ 获取今天所有人的投票汇总 :return: 品类->数量 """ all_menu = list(fetch_all_user_today_menu()) if len(all_menu) > 0: menus = list(map(lambda x: json.loads(x[1]), all_menu)) menu_keys = set() for x in menus: for k in x: menu_keys.add(k) result = {} for k in menu_keys: result[k] = 0 for x in menus: for k in x: result[k] += x[k] return result return {} def within_time() -> bool: """ 判断是否在投票时间内 :return: 是否 """ start_time = datetime.strptime(str(datetime.now().date()) + ' 8:00', '%Y-%m-%d %H:%M') end_time = datetime.strptime(str(datetime.now().date()) + ' 17:30', '%Y-%m-%d %H:%M') if start_time < datetime.now() < end_time: return True return False def check_roll() -> int: """ 判断是否能抽签 :return: 0 不可以, 1 可以, -1 已抽过 """ result = fetch_roll_result() if result is not None: return -1 return 0 if within_time() else 1 def vote_reduce(summary: dict[str, float]) -> dict[str, float]: """ 降低昨天点过的餐的中奖率 :param summary: 投票汇总结果 :return: 投票汇总结果 """ last_result = fetch_roll_result(-1) for k in summary: if last_result == k: summary[k] = summary[k] * 7 / 10 return summary @app.route('/dinner/update') def dinner_update(): """ 更新投票 :return: 响应内容 """ user_agent_string = request.headers.get('User-Agent') if not is_mobile_request(user_agent_string): abort(403) if check_roll() != 0: return make_response(json.dumps(dict(code=-1, data="来晚了,提交失败"))) value = request.args.get('value').strip() if not value: set_user_menu('') return make_response(json.dumps(dict(code=0, data="OK"))) value = json.loads(value) summary = 0 for key in value: summary += int(value[key]) if summary <= 0: set_user_menu('') return make_response(json.dumps(dict(code=0, data="OK"))) for key in value: value[key] = int(value[key]) / summary set_user_menu(json.dumps(value, ensure_ascii=False)) return make_response(json.dumps(dict(code=0, data="OK"))) @app.route('/dinner/roll') def dinner_roll(): """ 发起抽签 :return: 响应 """ if check_roll() != 1: return make_response(json.dumps(dict(code=-1, data="目前不能抽签"))) summary = vote_reduce(fetch_user_menu_summary()) for k in summary: summary[k] = int(round(summary[k] * 100)) pool = [] for k in summary: for i in range(int(summary[k])): pool.append(k) random.shuffle(pool) result = pool[0] set_roll_result(result) return make_response(json.dumps(dict(code=0, data="OK"))) @app.route('/dinner') def dinner(): """ 主页面 :return: 响应 """ menu = get_user_menu() if menu: menu = json.loads(menu) else: menu = {} summary = vote_reduce(fetch_user_menu_summary()) last_result = fetch_roll_result(-1) total_vote = sum(value for value in summary.values()) result = fetch_roll_result() can_roll = (check_roll() == 1) all_choice = list(map(lambda x: {'name': x[0], 'label': x[1]}, fetch_all_menu())) return render_template('dinner.html', all_choice=all_choice, menu=menu, summary=summary, total_vote=total_vote, result=result, can_roll=can_roll, last_result=last_result)