重构,添加注释
This commit is contained in:
parent
9ba075559c
commit
c6f7658c0f
|
@ -1,2 +1,3 @@
|
||||||
/.idea/
|
/.idea/
|
||||||
*.sqlite3
|
*.sqlite3
|
||||||
|
/__pycache__/
|
59
dao.py
59
dao.py
|
@ -1,14 +1,15 @@
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from typing import Generator
|
||||||
|
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
||||||
db_path = './data.sqlite3'
|
db_path = './data.sqlite3'
|
||||||
|
|
||||||
db = sqlite3.connect(db_path)
|
ddl_db = sqlite3.connect(db_path)
|
||||||
cursor = db.cursor()
|
ddl_cursor = ddl_db.cursor()
|
||||||
try:
|
try:
|
||||||
cursor.execute('''
|
ddl_cursor.execute('''
|
||||||
create table if not exists user_menu
|
create table if not exists user_menu
|
||||||
(
|
(
|
||||||
user text,
|
user text,
|
||||||
|
@ -17,32 +18,40 @@ create table if not exists user_menu
|
||||||
primary key (user, datestr)
|
primary key (user, datestr)
|
||||||
)
|
)
|
||||||
''')
|
''')
|
||||||
cursor.execute('''
|
ddl_cursor.execute('''
|
||||||
create table if not exists roll_result
|
create table if not exists roll_result
|
||||||
(
|
(
|
||||||
datestr text primary key,
|
datestr text primary key,
|
||||||
value text
|
value text
|
||||||
)
|
)
|
||||||
''')
|
''')
|
||||||
cursor.execute('''
|
ddl_cursor.execute('''
|
||||||
create table if not exists menu
|
create table if not exists menu
|
||||||
(
|
(
|
||||||
name text primary key,
|
name text primary key,
|
||||||
label text
|
label text
|
||||||
)
|
)
|
||||||
''')
|
''')
|
||||||
db.commit()
|
ddl_db.commit()
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
ddl_cursor.close()
|
||||||
db.close()
|
ddl_db.close()
|
||||||
|
|
||||||
|
|
||||||
def get_user():
|
def get_user() -> str:
|
||||||
|
"""
|
||||||
|
根据访问IP决定用户ID
|
||||||
|
:return: 用户ID
|
||||||
|
"""
|
||||||
client_ip = request.remote_addr
|
client_ip = request.remote_addr
|
||||||
return client_ip
|
return client_ip
|
||||||
|
|
||||||
|
|
||||||
def get_user_menu():
|
def get_user_menu() -> str:
|
||||||
|
"""
|
||||||
|
获取当前用户的投票内容
|
||||||
|
:return: 投票内容
|
||||||
|
"""
|
||||||
user = get_user()
|
user = get_user()
|
||||||
db = sqlite3.connect(db_path)
|
db = sqlite3.connect(db_path)
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
|
@ -63,7 +72,12 @@ def get_user_menu():
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
def set_user_menu(menu, user=None):
|
def set_user_menu(menu: str, user: str = None) -> None:
|
||||||
|
"""
|
||||||
|
设置用户投票内容
|
||||||
|
:param menu: 投票内容
|
||||||
|
:param user: 用户,默认当前用户
|
||||||
|
"""
|
||||||
datestr = datetime.now().strftime('%Y-%m-%d')
|
datestr = datetime.now().strftime('%Y-%m-%d')
|
||||||
if user is None:
|
if user is None:
|
||||||
user = get_user()
|
user = get_user()
|
||||||
|
@ -78,7 +92,10 @@ def set_user_menu(menu, user=None):
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
def fetch_all_today_menu():
|
def fetch_all_user_today_menu() -> Generator[tuple[str, str], None, None]:
|
||||||
|
"""
|
||||||
|
获取所有用户今日的投票内容
|
||||||
|
"""
|
||||||
datestr = datetime.now().strftime('%Y-%m-%d')
|
datestr = datetime.now().strftime('%Y-%m-%d')
|
||||||
db = sqlite3.connect(db_path)
|
db = sqlite3.connect(db_path)
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
|
@ -94,7 +111,10 @@ def fetch_all_today_menu():
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
def fetch_all_menu():
|
def fetch_all_menu() -> Generator[tuple[str, str], None, None]:
|
||||||
|
"""
|
||||||
|
获取所有可点的菜单
|
||||||
|
"""
|
||||||
db = sqlite3.connect(db_path)
|
db = sqlite3.connect(db_path)
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
try:
|
try:
|
||||||
|
@ -108,7 +128,12 @@ def fetch_all_menu():
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
def fetch_roll_result(interval=0):
|
def fetch_roll_result(interval: int = 0) -> str | None:
|
||||||
|
"""
|
||||||
|
获取N天前的抽签结果
|
||||||
|
:param interval: 间隔,天
|
||||||
|
:return: 抽签结果
|
||||||
|
"""
|
||||||
date = datetime.now() + timedelta(days=interval)
|
date = datetime.now() + timedelta(days=interval)
|
||||||
datestr = date.strftime('%Y-%m-%d')
|
datestr = date.strftime('%Y-%m-%d')
|
||||||
db = sqlite3.connect(db_path)
|
db = sqlite3.connect(db_path)
|
||||||
|
@ -125,7 +150,11 @@ def fetch_roll_result(interval=0):
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
def set_roll_result(value):
|
def set_roll_result(value: str) -> None:
|
||||||
|
"""
|
||||||
|
写入抽签结果
|
||||||
|
:param value: 抽签结果
|
||||||
|
"""
|
||||||
datestr = datetime.now().strftime('%Y-%m-%d')
|
datestr = datetime.now().strftime('%Y-%m-%d')
|
||||||
db = sqlite3.connect(db_path)
|
db = sqlite3.connect(db_path)
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
|
|
75
dinner.py
75
dinner.py
|
@ -1,23 +1,35 @@
|
||||||
import json
|
import json
|
||||||
|
from re import Pattern
|
||||||
|
|
||||||
from session import app
|
from session import app
|
||||||
from flask import send_from_directory, render_template, request, make_response, abort
|
from flask import render_template, make_response, abort
|
||||||
import re
|
import re
|
||||||
import random
|
import random
|
||||||
from dao import *
|
from dao import *
|
||||||
|
|
||||||
MOBILE_AGENTS_PATTERN = re.compile(
|
MOBILE_AGENTS_PATTERN: Pattern[str] = re.compile(
|
||||||
r"(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino",
|
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,
|
re.IGNORECASE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def is_mobile_request(user_agent):
|
def is_mobile_request(user_agent: str) -> bool:
|
||||||
|
"""
|
||||||
|
判断是否是移动端
|
||||||
|
:param user_agent: UA
|
||||||
|
:return: 是否
|
||||||
|
"""
|
||||||
return bool(MOBILE_AGENTS_PATTERN.search(user_agent))
|
return bool(MOBILE_AGENTS_PATTERN.search(user_agent))
|
||||||
|
|
||||||
|
|
||||||
def fetch_menu_summary():
|
def fetch_user_menu_summary() -> dict[str, float]:
|
||||||
all_menu = list(fetch_all_today_menu())
|
"""
|
||||||
|
获取今天所有人的投票汇总
|
||||||
|
:return: 品类->数量
|
||||||
|
"""
|
||||||
|
all_menu = list(fetch_all_user_today_menu())
|
||||||
if len(all_menu) > 0:
|
if len(all_menu) > 0:
|
||||||
menus = list(map(lambda x: json.loads(x[1]), all_menu))
|
menus = list(map(lambda x: json.loads(x[1]), all_menu))
|
||||||
menu_keys = set()
|
menu_keys = set()
|
||||||
|
@ -31,10 +43,14 @@ def fetch_menu_summary():
|
||||||
for k in x:
|
for k in x:
|
||||||
result[k] += x[k]
|
result[k] += x[k]
|
||||||
return result
|
return result
|
||||||
return []
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def within_time():
|
def within_time() -> bool:
|
||||||
|
"""
|
||||||
|
判断是否在投票时间内
|
||||||
|
:return: 是否
|
||||||
|
"""
|
||||||
start_time = datetime.strptime(str(datetime.now().date()) + ' 8:00', '%Y-%m-%d %H:%M')
|
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')
|
end_time = datetime.strptime(str(datetime.now().date()) + ' 17:30', '%Y-%m-%d %H:%M')
|
||||||
if start_time < datetime.now() < end_time:
|
if start_time < datetime.now() < end_time:
|
||||||
|
@ -42,15 +58,36 @@ def within_time():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def check_roll():
|
def check_roll() -> int:
|
||||||
|
"""
|
||||||
|
判断是否能抽签
|
||||||
|
:return: 0 不可以, 1 可以, -1 已抽过
|
||||||
|
"""
|
||||||
result = fetch_roll_result()
|
result = fetch_roll_result()
|
||||||
if result is not None:
|
if result is not None:
|
||||||
return -1
|
return -1
|
||||||
return 0 if within_time() else 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')
|
@app.route('/dinner/update')
|
||||||
def dinner_update():
|
def dinner_update():
|
||||||
|
"""
|
||||||
|
更新投票
|
||||||
|
:return: 响应内容
|
||||||
|
"""
|
||||||
user_agent_string = request.headers.get('User-Agent')
|
user_agent_string = request.headers.get('User-Agent')
|
||||||
if not is_mobile_request(user_agent_string):
|
if not is_mobile_request(user_agent_string):
|
||||||
abort(403)
|
abort(403)
|
||||||
|
@ -75,17 +112,18 @@ def dinner_update():
|
||||||
|
|
||||||
@app.route('/dinner/roll')
|
@app.route('/dinner/roll')
|
||||||
def dinner_roll():
|
def dinner_roll():
|
||||||
|
"""
|
||||||
|
发起抽签
|
||||||
|
:return: 响应
|
||||||
|
"""
|
||||||
if check_roll() != 1:
|
if check_roll() != 1:
|
||||||
return make_response(json.dumps(dict(code=-1, data="目前不能抽签")))
|
return make_response(json.dumps(dict(code=-1, data="目前不能抽签")))
|
||||||
summary = fetch_menu_summary()
|
summary = vote_reduce(fetch_user_menu_summary())
|
||||||
last_result = fetch_roll_result(-1)
|
|
||||||
for k in summary:
|
for k in summary:
|
||||||
if last_result == k:
|
|
||||||
summary[k] = summary[k] * 7 / 10
|
|
||||||
summary[k] = int(round(summary[k] * 100))
|
summary[k] = int(round(summary[k] * 100))
|
||||||
pool = []
|
pool = []
|
||||||
for k in summary:
|
for k in summary:
|
||||||
for i in range(summary[k]):
|
for i in range(int(summary[k])):
|
||||||
pool.append(k)
|
pool.append(k)
|
||||||
random.shuffle(pool)
|
random.shuffle(pool)
|
||||||
result = pool[0]
|
result = pool[0]
|
||||||
|
@ -95,16 +133,17 @@ def dinner_roll():
|
||||||
|
|
||||||
@app.route('/dinner')
|
@app.route('/dinner')
|
||||||
def dinner():
|
def dinner():
|
||||||
|
"""
|
||||||
|
主页面
|
||||||
|
:return: 响应
|
||||||
|
"""
|
||||||
menu = get_user_menu()
|
menu = get_user_menu()
|
||||||
if menu:
|
if menu:
|
||||||
menu = json.loads(menu)
|
menu = json.loads(menu)
|
||||||
else:
|
else:
|
||||||
menu = {}
|
menu = {}
|
||||||
summary = fetch_menu_summary()
|
summary = vote_reduce(fetch_user_menu_summary())
|
||||||
last_result = fetch_roll_result(-1)
|
last_result = fetch_roll_result(-1)
|
||||||
for x in summary:
|
|
||||||
if x == last_result:
|
|
||||||
summary[x] = summary[x] * 7 / 10
|
|
||||||
total_vote = sum(value for value in summary.values())
|
total_vote = sum(value for value in summary.values())
|
||||||
if total_vote == 0:
|
if total_vote == 0:
|
||||||
total_vote = 1
|
total_vote = 1
|
||||||
|
|
6
start.py
6
start.py
|
@ -1,16 +1,18 @@
|
||||||
import subprocess, os
|
import os
|
||||||
from flask import render_template, redirect
|
from flask import redirect, send_from_directory
|
||||||
import threading
|
import threading
|
||||||
from dinner import *
|
from dinner import *
|
||||||
from session import app
|
from session import app
|
||||||
|
|
||||||
lock = threading.Lock()
|
lock = threading.Lock()
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
return redirect('dinner')
|
return redirect('dinner')
|
||||||
# return render_template('index.html')
|
# return render_template('index.html')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/favicon.ico')
|
@app.route('/favicon.ico')
|
||||||
def favicon():
|
def favicon():
|
||||||
return send_from_directory(os.path.join(app.root_path, 'static'), 'fd-logo.png')
|
return send_from_directory(os.path.join(app.root_path, 'static'), 'fd-logo.png')
|
||||||
|
|
Loading…
Reference in New Issue