dinner_vote/dinner.py

159 lines
4.5 KiB
Python

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)