From 123554e24db07f4bc8bd152215ce2b0b00b3c8d4 Mon Sep 17 00:00:00 2001 From: Lost-MSth Date: Fri, 30 Oct 2020 20:17:21 +0800 Subject: [PATCH] Update to v1.4 --- .../database/arcaea_database.db | Bin 77824 -> 77824 bytes {v1.3 => latest version}/database/arcsong.db | Bin 106496 -> 106496 bytes .../database/database_initialize.py | 502 +-- .../database/map/byd_dement.json | 100 +- .../database/map/byd_fairytale.json | 88 +- .../database/map/byd_goodtek.json | 134 +- .../database/map/byd_infinityheaven.json | 180 +- .../database/map/byd_purgatorium.json | 120 +- .../database/map/byd_vexaria.json | 82 +- .../database/map/chapter3_conflict.json | 854 ++--- .../database/map/chapter3_conflict_2.json | 534 ++-- .../database/map/chapter4_ripples.json | 470 +-- .../database/map/chapter4_the_calm.json | 1550 +++++----- .../database/map/chapter4_waves.json | 396 +-- .../database/map/extra_originals.json | 952 +++--- .../database/map/hikari_art.json | 812 ++--- .../database/map/hikari_happy.json | 1188 +++---- .../database/map/tairitsu_arcs.json | 1188 +++---- .../database/map/tairitsu_tech.json | 812 ++--- .../database/map/test.json | 186 +- .../database/map/test2.json | 238 +- latest version/database/songs/dement/3.aff | 21 + {v1.3 => latest version}/main.py | 1157 +++---- {v1.3 => latest version}/run.bat | 0 latest version/server/arcdownload.py | 48 + {v1.3 => latest version}/server/arcscore.py | 2744 ++++++++--------- {v1.3 => latest version}/server/arcworld.py | 518 ++-- {v1.3 => latest version}/server/auth.py | 300 +- {v1.3 => latest version}/server/info.py | 982 +++--- {v1.3 => latest version}/server/setme.py | 310 +- {v1.3 => latest version}/setting.ini | 4 +- {v1.3 => latest version}/static/style.css | 432 +-- {v1.3 => latest version}/templates/base.html | 44 +- .../templates/web/allplayer.html | 160 +- .../templates/web/allsong.html | 94 +- .../templates/web/changesong.html | 68 +- .../templates/web/index.html | 46 +- .../templates/web/login.html | 26 +- .../templates/web/singlecharttop.html | 214 +- .../templates/web/singleplayer.html | 168 +- .../templates/web/singleplayerptt.html | 380 +-- .../templates/web/updatedatabase.html | 40 +- {v1.3 => latest version}/web/index.py | 720 ++--- {v1.3 => latest version}/web/login.py | 100 +- {v1.3 => latest version}/web/system.py | 226 +- {v1.3 => latest version}/web/webscore.py | 208 +- 46 files changed, 9758 insertions(+), 9638 deletions(-) rename {v1.3 => latest version}/database/arcaea_database.db (97%) rename {v1.3 => latest version}/database/arcsong.db (81%) rename {v1.3 => latest version}/database/database_initialize.py (95%) rename {v1.3 => latest version}/database/map/byd_dement.json (95%) rename {v1.3 => latest version}/database/map/byd_fairytale.json (96%) rename {v1.3 => latest version}/database/map/byd_goodtek.json (95%) rename {v1.3 => latest version}/database/map/byd_infinityheaven.json (95%) rename {v1.3 => latest version}/database/map/byd_purgatorium.json (96%) rename {v1.3 => latest version}/database/map/byd_vexaria.json (95%) rename {v1.3 => latest version}/database/map/chapter3_conflict.json (95%) rename {v1.3 => latest version}/database/map/chapter3_conflict_2.json (95%) rename {v1.3 => latest version}/database/map/chapter4_ripples.json (95%) rename {v1.3 => latest version}/database/map/chapter4_the_calm.json (95%) rename {v1.3 => latest version}/database/map/chapter4_waves.json (95%) rename {v1.3 => latest version}/database/map/extra_originals.json (95%) rename {v1.3 => latest version}/database/map/hikari_art.json (95%) rename {v1.3 => latest version}/database/map/hikari_happy.json (95%) rename {v1.3 => latest version}/database/map/tairitsu_arcs.json (95%) rename {v1.3 => latest version}/database/map/tairitsu_tech.json (95%) rename {v1.3 => latest version}/database/map/test.json (95%) rename {v1.3 => latest version}/database/map/test2.json (95%) create mode 100644 latest version/database/songs/dement/3.aff rename {v1.3 => latest version}/main.py (91%) rename {v1.3 => latest version}/run.bat (100%) create mode 100644 latest version/server/arcdownload.py rename {v1.3 => latest version}/server/arcscore.py (97%) rename {v1.3 => latest version}/server/arcworld.py (96%) rename {v1.3 => latest version}/server/auth.py (97%) rename {v1.3 => latest version}/server/info.py (96%) rename {v1.3 => latest version}/server/setme.py (97%) rename {v1.3 => latest version}/setting.ini (95%) rename {v1.3 => latest version}/static/style.css (93%) rename {v1.3 => latest version}/templates/base.html (97%) rename {v1.3 => latest version}/templates/web/allplayer.html (97%) rename {v1.3 => latest version}/templates/web/allsong.html (96%) rename {v1.3 => latest version}/templates/web/changesong.html (97%) rename {v1.3 => latest version}/templates/web/index.html (98%) rename {v1.3 => latest version}/templates/web/login.html (96%) rename {v1.3 => latest version}/templates/web/singlecharttop.html (97%) rename {v1.3 => latest version}/templates/web/singleplayer.html (97%) rename {v1.3 => latest version}/templates/web/singleplayerptt.html (97%) rename {v1.3 => latest version}/templates/web/updatedatabase.html (97%) rename {v1.3 => latest version}/web/index.py (96%) rename {v1.3 => latest version}/web/login.py (96%) rename {v1.3 => latest version}/web/system.py (98%) rename {v1.3 => latest version}/web/webscore.py (96%) diff --git a/v1.3/database/arcaea_database.db b/latest version/database/arcaea_database.db similarity index 97% rename from v1.3/database/arcaea_database.db rename to latest version/database/arcaea_database.db index 8a001576011ccfbccf3f3ed5a13fbf27cf9c41dc..a1852a5269a729e4802e36724dd96663cf646c96 100644 GIT binary patch delta 190 zcmZp8z|!!5Wy33Z4if`Y10!<_i_M?pg$kI}xcervPw-~q?%OOVV8tybqb9)2$jHRR z$jHdc!2v`ZaxD#Na)~PvS42fcZC*1wf`wU)uYEH60&gb1cAy?(J}yocpcarawapXP z6*DrcaTQEv-{8%}RRENi;Zl@W6J!)eG81U3nrlgEN-EsgiMxtfnbr8^C$k^$X5yCz SYCFxx#tJkQXr$`-+X(>bAumz@ delta 95 zcmZp8z|!!5Wy33Z4kIIDV^a%rgUz4hg$kHexz|i)pWwY&P#}tX^P1TaEX=BW6DPAT t0EyW1ZJxNUn2}kP3n;PyEW)*U;;v#=W>tRG$?OL}BA59#tDe7|000n^Ag2HT diff --git a/v1.3/database/arcsong.db b/latest version/database/arcsong.db similarity index 81% rename from v1.3/database/arcsong.db rename to latest version/database/arcsong.db index e2a2ba9cd13762692636be8ca84cd53c9609c197..33a74abfdba81ff43d4dd143ca1147992316908c 100644 GIT binary patch delta 9197 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 Iv=YGbe{O!+8UO$Q delta 8430 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 R@Xt~@(A?/toggle_uncap', methods=['POST']) # 角色觉醒切换 -def character_uncap(path): - character_id = int(path[22:]) - headers = request.headers - token = headers['Authorization'] - token = token[7:] - try: - user_id = server.auth.token_get_id(token) - if user_id is not None: - r = server.setme.change_char_uncap(user_id, character_id) - if r is not None: - return jsonify({ - "success": True, - "value": { - "user_id": user_id, - "character": [r] - } - }) - else: - return error_return(108) - else: - return error_return(108) - except: - return error_return(108) - - -@app.route('/coffee/12/friend/me/add', methods=['POST']) # 加好友 -def add_friend(): - headers = request.headers - token = headers['Authorization'] - token = token[7:] - friend_code = request.form['friend_code'] - try: - user_id = server.auth.token_get_id(token) - friend_id = server.auth.code_get_id(friend_code) - if user_id is not None and friend_id is not None: - r = server.setme.arc_add_friend(user_id, friend_id) - if r is not None and r != 602 and r != 604: - return jsonify({ - "success": True, - "value": { - "user_id": user_id, - "updatedAt": "2020-09-07T07:32:12.740Z", - "createdAt": "2020-09-06T10:05:18.471Z", - "friends": r - } - }) - else: - if r is not None: - return error_return(r) - else: - return error_return(108) - else: - if friend_id is None: - return error_return(401) - else: - return error_return(108) - except: - return error_return(108) - - -@app.route('/coffee/12/friend/me/delete', methods=['POST']) # 删好友 -def delete_friend(): - headers = request.headers - token = headers['Authorization'] - token = token[7:] - friend_id = int(request.form['friend_id']) - try: - user_id = server.auth.token_get_id(token) - if user_id is not None and friend_id is not None: - r = server.setme.arc_delete_friend(user_id, friend_id) - if r is not None: - return jsonify({ - "success": True, - "value": { - "user_id": user_id, - "updatedAt": "2020-09-07T07:32:12.740Z", - "createdAt": "2020-09-06T10:05:18.471Z", - "friends": r - } - }) - else: - return error_return(108) - else: - if friend_id is None: - return error_return(401) - else: - return error_return(108) - except: - return error_return(108) - - -@app.route('/coffee/12/score/song/friend', methods=['GET']) # 好友排名,默认最多50 -def song_score_friend(): - song_id = request.args.get('song_id') - difficulty = request.args.get('difficulty') - headers = request.headers - token = headers['Authorization'] - token = token[7:] - try: - user_id = server.auth.token_get_id(token) - if user_id is not None: - r = server.arcscore.arc_score_friend(user_id, song_id, difficulty) - if r is not None: - return jsonify({ - "success": True, - "value": r - }) - else: - return error_return(108) - else: - return error_return(108) - except: - return error_return(108) - - -@app.route('/coffee/12/score/song/me', methods=['GET']) # 我的排名,默认最多20 -def song_score_me(): - song_id = request.args.get('song_id') - difficulty = request.args.get('difficulty') - headers = request.headers - token = headers['Authorization'] - token = token[7:] - try: - user_id = server.auth.token_get_id(token) - if user_id is not None: - r = server.arcscore.arc_score_me(user_id, song_id, difficulty) - if r is not None: - return jsonify({ - "success": True, - "value": r - }) - else: - return error_return(108) - else: - return error_return(108) - except: - return error_return(108) - - -@app.route('/coffee/12/score/song', methods=['GET']) # TOP20 -def song_score_top(): - song_id = request.args.get('song_id') - difficulty = request.args.get('difficulty') - headers = request.headers - token = headers['Authorization'] - token = token[7:] - try: - user_id = server.auth.token_get_id(token) - if user_id is not None: - r = server.arcscore.arc_score_top(song_id, difficulty) - if r is not None: - return jsonify({ - "success": True, - "value": r - }) - else: - return error_return(108) - else: - return error_return(108) - except: - return error_return(108) - - -@app.route('/coffee/12/score/song', methods=['POST']) # 成绩上传 -def song_score_post(): - headers = request.headers - token = headers['Authorization'] - token = token[7:] - song_id = request.form['song_id'] - difficulty = int(request.form['difficulty']) - score = int(request.form['score']) - shiny_perfect_count = int(request.form['shiny_perfect_count']) - perfect_count = int(request.form['perfect_count']) - near_count = int(request.form['near_count']) - miss_count = int(request.form['miss_count']) - health = int(request.form['health']) - modifier = int(request.form['modifier']) - beyond_gauge = int(request.form['beyond_gauge']) - clear_type = int(request.form['clear_type']) - - try: - user_id = server.auth.token_get_id(token) - if user_id is not None: - r, re = server.arcscore.arc_score_post(user_id, song_id, difficulty, score, shiny_perfect_count, - perfect_count, near_count, miss_count, health, modifier, beyond_gauge, clear_type) - if r: - if re: - return jsonify({ - "success": True, - "value": re - }) - else: - return jsonify({ - "success": True, - "value": {"user_rating": r} - }) - else: - return error_return(108) - else: - return error_return(108) - except: - return error_return(108) - - -@app.route('/coffee/12/score/token', methods=['GET']) # 成绩上传所需的token,显然我不想验证 -def score_token(): - return jsonify({ - "success": True, - "value": { - "token": "1145141919810" - } - }) - - -# 世界模式成绩上传所需的token,无验证 -@app.route('/coffee/12/score/token/world', methods=['GET']) -def score_token_world(): - headers = request.headers - token = headers['Authorization'] - token = token[7:] - args = request.args - try: - user_id = server.auth.token_get_id(token) - if user_id: - server.arcworld.play_world_song(user_id, args) - return jsonify({ - "success": True, - "value": { - "stamina": 12, - "max_stamina_ts": 1599547603825, - "token": "13145201919810" - } - }) - else: - return error_return(108) - except: - return error_return(108) - - -@app.route('/coffee/12/user/me/save', methods=['GET']) # 从云端同步 -def cloud_get(): - headers = request.headers - token = headers['Authorization'] - token = token[7:] - try: - user_id = server.auth.token_get_id(token) - if user_id is not None: - r = server.arcscore.arc_all_get(user_id) - if r is not None: - return jsonify({ - "success": True, - "value": r - }) - else: - return error_return(108) - else: - return error_return(108) - except: - return error_return(108) - - -@app.route('/coffee/12/user/me/save', methods=['POST']) # 向云端同步 -def cloud_post(): - headers = request.headers - token = headers['Authorization'] - token = token[7:] - scores_data = request.form['scores_data'] - clearlamps_data = request.form['clearlamps_data'] - try: - user_id = server.auth.token_get_id(token) - if user_id is not None: - server.arcscore.arc_all_post(user_id, scores_data, clearlamps_data) - return jsonify({ - "success": True, - "value": { - "user_id": user_id - } - }) - else: - return error_return(108) - except: - return error_return(108) - - -@app.route('/coffee/12/purchase/me/redeem', methods=['POST']) # 兑换码,自然没有用 -def redeem(): - return error_return(504) - - -# 购买,自然没有用,只是为了world模式boost一下 -@app.route('/coffee/12/purchase/me/item', methods=['POST']) -def item(): - return jsonify({ - "success": True - }) - - -@app.route('/coffee/12/purchase/me/pack', methods=['POST']) # 购买,自然没有用 -def pack(): - return jsonify({ - "success": True - }) - - -@app.route('/coffee/12/purchase/bundle/single', methods=['GET']) # 单曲购买,自然没有用 -def single(): - return jsonify({ - "success": True, - "value": [{ - "name": "testsingle", - "items": [{ - "id": "testsingle", - "type": "single", - "is_available": False - }], - "price": 100, - "orig_price": 100 - }] - }) - - -@app.route('/coffee/12/world/map/me', methods=['GET']) # 获得世界模式信息,所有地图 -def world_all(): - headers = request.headers - token = headers['Authorization'] - token = token[7:] - try: - user_id = server.auth.token_get_id(token) - if user_id: - return jsonify({ - "success": True, - "value": { - "current_map": server.arcworld.get_current_map(user_id), - "user_id": user_id, - "maps": server.arcworld.get_world_all(user_id) - } - }) - else: - return error_return(108) - except: - return error_return(108) - - -@app.route('/coffee/12/world/map/me/', methods=['POST']) # 进入地图 -def world_in(): - headers = request.headers - token = headers['Authorization'] - token = token[7:] - map_id = request.form['map_id'] - try: - user_id = server.auth.token_get_id(token) - if user_id: - return jsonify({ - "success": True, - "value": server.arcworld.get_user_world(user_id, map_id) - }) - else: - return error_return(108) - except: - return error_return(108) - - -@app.route('/coffee/12/world/map/me/', methods=['GET']) # 获得单个地图完整信息 -def world_one(map_id): - headers = request.headers - token = headers['Authorization'] - token = token[7:] - try: - user_id = server.auth.token_get_id(token) - if user_id: - server.arcworld.change_user_current_map(user_id, map_id) - return jsonify({ - "success": True, - "value": { - "user_id": user_id, - "current_map": map_id, - "maps": [server.arcworld.get_user_world_info(user_id, map_id)] - } - }) - else: - return error_return(108) - except: - return error_return(108) - - -@app.route('/coffee/', methods=['POST']) # 三个设置,写在最后降低优先级 -def sys_set(path): - set_arg = path[10:] - headers = request.headers - token = headers['Authorization'] - token = token[7:] - value = request.form['value'] - - try: - user_id = server.auth.token_get_id(token) - if user_id is not None: - server.setme.arc_sys_set(user_id, value, set_arg) - r = server.info.arc_aggregate_small(user_id) - r['value'] = r['value'][0]['value'] - return jsonify(r) - else: - return error_return(108) - except: - return error_return(108) - - -def main(): - config = configparser.ConfigParser() - path = r'setting.ini' - config.read(path, encoding="utf-8") - HOST = config.get('CONFIG', 'HOST') - PORT = config.get('CONFIG', 'PORT') - app.config.from_mapping(SECRET_KEY='1145141919810') - app.register_blueprint(web.login.bp) - app.register_blueprint(web.index.bp) - - app.run(HOST, PORT) - - -if __name__ == '__main__': - main() - - -# Made By Lost 2020.9.11 +from flask import Flask, request, jsonify, make_response, send_from_directory +import configparser +import base64 +import server.auth +import server.info +import server.setme +import server.arcscore +import web.login +import web.index +import server.arcworld +import server.arcdownload +import os + +app = Flask(__name__) +wsgi_app = app.wsgi_app + + +def error_return(error_code): # 错误返回 + # 100 无法在此ip地址下登录游戏 + # 101 用户名占用 + # 102 电子邮箱已注册 + # 103 已有一个账号由此设备创建 + # 104 用户名密码错误 + # 105 24小时内登入两台设备 + # 106 账户冻结 + # 107 你没有足够的体力 + # 113 活动已结束 + # 114 该活动已结束,您的成绩不会提交 + # 120 封号警告 + # 121 账户冻结 + # 122 账户暂时冻结 + # 123 账户被限制 + # 150 非常抱歉您已被限制使用此功能 + # 151 目前无法使用此功能 + # 401 用户不存在 + # 403 无法连接至服务器 + # 501 502 此物品目前无法获取 + # 504 无效的序列码 + # 505 此序列码已被使用 + # 506 你已拥有了此物品 + # 601 好友列表已满 + # 602 此用户已是好友 + # 604 你不能加自己为好友 + # 1001 设备数量达到上限 + # 1002 该设备已使用过本功能 + # 其它 发生未知错误 + return jsonify({ + "success": False, + "error_code": error_code + }) + + +@app.route('/') +def hello(): + return "Hello World!" + + +@app.route('/coffee/12/auth/login', methods=['POST']) # 登录接口 +def login(): + headers = request.headers + id_pwd = headers['Authorization'] + id_pwd = base64.b64decode(id_pwd[6:]).decode() + name, password = id_pwd.split(':', 1) + + try: + token = server.auth.arc_login(name, password) + if token is not None: + r = {"success": True, "token_type": "Bearer"} + r['access_token'] = token + return jsonify(r) + else: + return error_return(104) # 用户名或密码错误 + except: + return error_return(108) + + +@app.route('/coffee/12/user/', methods=['POST']) # 注册接口 +def register(): + name = request.form['name'] + password = request.form['password'] + try: + user_id, token, error_code = server.auth.arc_register(name, password) + if user_id is not None: + r = {"success": True, "value": { + 'user_id': user_id, 'access_token': token}} + return jsonify(r) + else: + return error_return(error_code) # 应该是101,用户名被占用,毕竟电子邮箱、设备号没记录 + except: + return error_return(108) + + +@app.route('/coffee/12/compose/aggregate', methods=['GET']) # 用户信息获取 +def aggregate(): + calls = request.args.get('calls') + headers = request.headers + token = headers['Authorization'] + token = token[7:] + try: + user_id = server.auth.token_get_id(token) + if user_id is not None: + if calls == '[{ "endpoint": "/user/me", "id": 0 }]': # 极其沙雕的判断,我猜get的参数就两种 + r = server.info.arc_aggregate_small(user_id) + else: + r = server.info.arc_aggregate_big(user_id) + return jsonify(r) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee/12/user/me/character', methods=['POST']) # 角色切换 +def character_change(): + headers = request.headers + token = headers['Authorization'] + token = token[7:] + character_id = request.form['character'] + skill_sealed = request.form['skill_sealed'] + try: + user_id = server.auth.token_get_id(token) + if user_id is not None: + flag = server.setme.change_char( + user_id, character_id, skill_sealed) + if flag: + return jsonify({ + "success": True, + "value": { + "user_id": user_id, + "character": character_id + } + }) + else: + return error_return(108) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee//toggle_uncap', methods=['POST']) # 角色觉醒切换 +def character_uncap(path): + character_id = int(path[22:]) + headers = request.headers + token = headers['Authorization'] + token = token[7:] + try: + user_id = server.auth.token_get_id(token) + if user_id is not None: + r = server.setme.change_char_uncap(user_id, character_id) + if r is not None: + return jsonify({ + "success": True, + "value": { + "user_id": user_id, + "character": [r] + } + }) + else: + return error_return(108) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee/12/friend/me/add', methods=['POST']) # 加好友 +def add_friend(): + headers = request.headers + token = headers['Authorization'] + token = token[7:] + friend_code = request.form['friend_code'] + try: + user_id = server.auth.token_get_id(token) + friend_id = server.auth.code_get_id(friend_code) + if user_id is not None and friend_id is not None: + r = server.setme.arc_add_friend(user_id, friend_id) + if r is not None and r != 602 and r != 604: + return jsonify({ + "success": True, + "value": { + "user_id": user_id, + "updatedAt": "2020-09-07T07:32:12.740Z", + "createdAt": "2020-09-06T10:05:18.471Z", + "friends": r + } + }) + else: + if r is not None: + return error_return(r) + else: + return error_return(108) + else: + if friend_id is None: + return error_return(401) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee/12/friend/me/delete', methods=['POST']) # 删好友 +def delete_friend(): + headers = request.headers + token = headers['Authorization'] + token = token[7:] + friend_id = int(request.form['friend_id']) + try: + user_id = server.auth.token_get_id(token) + if user_id is not None and friend_id is not None: + r = server.setme.arc_delete_friend(user_id, friend_id) + if r is not None: + return jsonify({ + "success": True, + "value": { + "user_id": user_id, + "updatedAt": "2020-09-07T07:32:12.740Z", + "createdAt": "2020-09-06T10:05:18.471Z", + "friends": r + } + }) + else: + return error_return(108) + else: + if friend_id is None: + return error_return(401) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee/12/score/song/friend', methods=['GET']) # 好友排名,默认最多50 +def song_score_friend(): + song_id = request.args.get('song_id') + difficulty = request.args.get('difficulty') + headers = request.headers + token = headers['Authorization'] + token = token[7:] + try: + user_id = server.auth.token_get_id(token) + if user_id is not None: + r = server.arcscore.arc_score_friend(user_id, song_id, difficulty) + if r is not None: + return jsonify({ + "success": True, + "value": r + }) + else: + return error_return(108) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee/12/score/song/me', methods=['GET']) # 我的排名,默认最多20 +def song_score_me(): + song_id = request.args.get('song_id') + difficulty = request.args.get('difficulty') + headers = request.headers + token = headers['Authorization'] + token = token[7:] + try: + user_id = server.auth.token_get_id(token) + if user_id is not None: + r = server.arcscore.arc_score_me(user_id, song_id, difficulty) + if r is not None: + return jsonify({ + "success": True, + "value": r + }) + else: + return error_return(108) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee/12/score/song', methods=['GET']) # TOP20 +def song_score_top(): + song_id = request.args.get('song_id') + difficulty = request.args.get('difficulty') + headers = request.headers + token = headers['Authorization'] + token = token[7:] + try: + user_id = server.auth.token_get_id(token) + if user_id is not None: + r = server.arcscore.arc_score_top(song_id, difficulty) + if r is not None: + return jsonify({ + "success": True, + "value": r + }) + else: + return error_return(108) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee/12/score/song', methods=['POST']) # 成绩上传 +def song_score_post(): + headers = request.headers + token = headers['Authorization'] + token = token[7:] + song_id = request.form['song_id'] + difficulty = int(request.form['difficulty']) + score = int(request.form['score']) + shiny_perfect_count = int(request.form['shiny_perfect_count']) + perfect_count = int(request.form['perfect_count']) + near_count = int(request.form['near_count']) + miss_count = int(request.form['miss_count']) + health = int(request.form['health']) + modifier = int(request.form['modifier']) + beyond_gauge = int(request.form['beyond_gauge']) + clear_type = int(request.form['clear_type']) + + try: + user_id = server.auth.token_get_id(token) + if user_id is not None: + r, re = server.arcscore.arc_score_post(user_id, song_id, difficulty, score, shiny_perfect_count, + perfect_count, near_count, miss_count, health, modifier, beyond_gauge, clear_type) + if r: + if re: + return jsonify({ + "success": True, + "value": re + }) + else: + return jsonify({ + "success": True, + "value": {"user_rating": r} + }) + else: + return error_return(108) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee/12/score/token', methods=['GET']) # 成绩上传所需的token,显然我不想验证 +def score_token(): + return jsonify({ + "success": True, + "value": { + "token": "1145141919810" + } + }) + + +# 世界模式成绩上传所需的token,无验证 +@app.route('/coffee/12/score/token/world', methods=['GET']) +def score_token_world(): + headers = request.headers + token = headers['Authorization'] + token = token[7:] + args = request.args + try: + user_id = server.auth.token_get_id(token) + if user_id: + server.arcworld.play_world_song(user_id, args) + return jsonify({ + "success": True, + "value": { + "stamina": 12, + "max_stamina_ts": 1599547603825, + "token": "13145201919810" + } + }) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee/12/user/me/save', methods=['GET']) # 从云端同步 +def cloud_get(): + headers = request.headers + token = headers['Authorization'] + token = token[7:] + try: + user_id = server.auth.token_get_id(token) + if user_id is not None: + r = server.arcscore.arc_all_get(user_id) + if r is not None: + return jsonify({ + "success": True, + "value": r + }) + else: + return error_return(108) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee/12/user/me/save', methods=['POST']) # 向云端同步 +def cloud_post(): + headers = request.headers + token = headers['Authorization'] + token = token[7:] + scores_data = request.form['scores_data'] + clearlamps_data = request.form['clearlamps_data'] + try: + user_id = server.auth.token_get_id(token) + if user_id is not None: + server.arcscore.arc_all_post(user_id, scores_data, clearlamps_data) + return jsonify({ + "success": True, + "value": { + "user_id": user_id + } + }) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee/12/purchase/me/redeem', methods=['POST']) # 兑换码,自然没有用 +def redeem(): + return error_return(504) + + +# 购买,自然没有用,只是为了world模式boost一下 +@app.route('/coffee/12/purchase/me/item', methods=['POST']) +def item(): + return jsonify({ + "success": True + }) + + +@app.route('/coffee/12/purchase/me/pack', methods=['POST']) # 购买,自然没有用 +def pack(): + return jsonify({ + "success": True + }) + + +@app.route('/coffee/12/purchase/bundle/single', methods=['GET']) # 单曲购买,自然没有用 +def single(): + return jsonify({ + "success": True, + "value": [{ + "name": "testsingle", + "items": [{ + "id": "testsingle", + "type": "single", + "is_available": False + }], + "price": 100, + "orig_price": 100 + }] + }) + + +@app.route('/coffee/12/world/map/me', methods=['GET']) # 获得世界模式信息,所有地图 +def world_all(): + headers = request.headers + token = headers['Authorization'] + token = token[7:] + try: + user_id = server.auth.token_get_id(token) + if user_id: + return jsonify({ + "success": True, + "value": { + "current_map": server.arcworld.get_current_map(user_id), + "user_id": user_id, + "maps": server.arcworld.get_world_all(user_id) + } + }) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee/12/world/map/me/', methods=['POST']) # 进入地图 +def world_in(): + headers = request.headers + token = headers['Authorization'] + token = token[7:] + map_id = request.form['map_id'] + try: + user_id = server.auth.token_get_id(token) + if user_id: + return jsonify({ + "success": True, + "value": server.arcworld.get_user_world(user_id, map_id) + }) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee/12/world/map/me/', methods=['GET']) # 获得单个地图完整信息 +def world_one(map_id): + headers = request.headers + token = headers['Authorization'] + token = token[7:] + try: + user_id = server.auth.token_get_id(token) + if user_id: + server.arcworld.change_user_current_map(user_id, map_id) + return jsonify({ + "success": True, + "value": { + "user_id": user_id, + "current_map": map_id, + "maps": [server.arcworld.get_user_world_info(user_id, map_id)] + } + }) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/coffee/12/serve/download/me/song', methods=['GET']) # 歌曲下载 +def download_song(): + headers = request.headers + token = headers['Authorization'] + token = token[7:] + song_ids = request.args.getlist('sid') + + try: + user_id = server.auth.token_get_id(token) + if user_id: + re = {} + if not song_ids: + re = server.arcdownload.get_all_songs() + else: + for song_id in song_ids: + re.update(server.arcdownload.get_one_song(song_id)) + + return jsonify({ + "success": True, + "value": re + }) + else: + return error_return(108) + except: + return error_return(108) + + +@app.route('/download/', methods=['GET']) # 下载 +def download(file_path): + try: + path = os.path.join('./database/songs', file_path) + if os.path.isfile(path) and not('../' in path or '..\\' in path): + return send_from_directory('./database/songs', file_path, as_attachment=True) + else: + return error_return(109) + except: + return error_return(108) + + +@app.route('/coffee/', methods=['POST']) # 三个设置,写在最后降低优先级 +def sys_set(path): + set_arg = path[10:] + headers = request.headers + token = headers['Authorization'] + token = token[7:] + value = request.form['value'] + + try: + user_id = server.auth.token_get_id(token) + if user_id is not None: + server.setme.arc_sys_set(user_id, value, set_arg) + r = server.info.arc_aggregate_small(user_id) + r['value'] = r['value'][0]['value'] + return jsonify(r) + else: + return error_return(108) + except: + return error_return(108) + + +def main(): + config = configparser.ConfigParser() + path = r'setting.ini' + config.read(path, encoding="utf-8") + HOST = config.get('CONFIG', 'HOST') + PORT = config.get('CONFIG', 'PORT') + app.config.from_mapping(SECRET_KEY='1145141919810') + app.register_blueprint(web.login.bp) + app.register_blueprint(web.index.bp) + + app.run(HOST, PORT) + + +if __name__ == '__main__': + main() + + +# Made By Lost 2020.9.11 diff --git a/v1.3/run.bat b/latest version/run.bat similarity index 100% rename from v1.3/run.bat rename to latest version/run.bat diff --git a/latest version/server/arcdownload.py b/latest version/server/arcdownload.py new file mode 100644 index 0000000..4ed2da7 --- /dev/null +++ b/latest version/server/arcdownload.py @@ -0,0 +1,48 @@ +import os +import hashlib +from flask import url_for + + +def get_file_md5(file_path): + # 计算文件MD5 + if not os.path.isfile(file_path): + return None + myhash = hashlib.md5() + f = open(file_path, 'rb') + while True: + b = f.read(8096) + if not b: + break + myhash.update(b) + f.close() + return myhash.hexdigest() + + +def get_one_song(song_id, file_dir='./database/songs'): + # 获取一首歌的下载链接,返回字典 + dir_list = os.listdir(os.path.join(file_dir, song_id)) + re = {} + for i in dir_list: + if os.path.isfile(os.path.join(file_dir, song_id, i)) and i in ['0.aff', '1.aff', '2.aff', '3.aff', 'base.ogg']: + if i == 'base.ogg': + re['audio'] = {"checksum": get_file_md5(os.path.join(file_dir, song_id, 'base.ogg')), + "url": url_for('download', file_path=song_id+'/base.ogg', _external=True)} + else: + if 'chart' not in re: + re['chart'] = {} + + re['chart'][i[0]] = {"checksum": get_file_md5(os.path.join(file_dir, song_id, i)), + "url": url_for('download', file_path=song_id+'/'+i, _external=True)} + + return {song_id: re} + + +def get_all_songs(file_dir='./database/songs'): + # 获取所有歌的下载链接,返回字典 + dir_list = os.listdir(file_dir) + re = {} + for i in dir_list: + if os.path.isdir(os.path.join(file_dir, i)): + re.update(get_one_song(i)) + + return re diff --git a/v1.3/server/arcscore.py b/latest version/server/arcscore.py similarity index 97% rename from v1.3/server/arcscore.py rename to latest version/server/arcscore.py index 1c0d350..c053697 100644 --- a/v1.3/server/arcscore.py +++ b/latest version/server/arcscore.py @@ -1,1372 +1,1372 @@ -import sqlite3 -import time -import json -import server.arcworld - - -def b2int(x): - # int与布尔值转换 - if x: - return 1 - else: - return 0 - - -def int2b(x): - # int与布尔值转换 - if x is None or x == 0: - return False - else: - return True - - -def get_score(c, user_id, song_id, difficulty): - # 根据user_id、song_id、难度得到该曲目最好成绩,返回字典 - c.execute('''select * from best_score where user_id = :a and song_id = :b and difficulty = :c''', - {'a': user_id, 'b': song_id, 'c': difficulty}) - x = c.fetchone() - if x is not None: - c.execute('''select name, character_id, is_skill_sealed, is_char_uncapped from user where user_id = :a''', { - 'a': user_id}) - y = c.fetchone() - if y is not None: - return { - "user_id": x[0], - "song_id": x[1], - "difficulty": x[2], - "score": x[3], - "shiny_perfect_count": x[4], - "perfect_count": x[5], - "near_count": x[6], - "miss_count": x[7], - "health": x[8], - "modifier": x[9], - "time_played": x[10], - "best_clear_type": x[11], - "clear_type": x[12], - "name": y[0], - "character": y[1], - "is_skill_sealed": int2b(y[2]), - "is_char_uncapped": int2b(y[3]) - } - else: - return {} - else: - return {} - - -def arc_score_friend(user_id, song_id, difficulty, limit=50): - # 得到用户好友分数表,默认最大50个 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - c.execute('''select user_id from best_score where user_id in (select :user_id union select user_id_other from friend where user_id_me = :user_id) and song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit''', { - 'user_id': user_id, 'song_id': song_id, 'difficulty': difficulty, 'limit': limit}) - x = c.fetchall() - r = [] - if x != []: - rank = 0 - for i in x: - rank += 1 - y = get_score(c, i[0], song_id, difficulty) - y['rank'] = rank - r.append(y) - - conn.commit() - conn.close() - return r - - -def arc_score_top(song_id, difficulty, limit=20): - # 得到top分数表,默认最多20个,如果是负数则全部查询 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - if limit >= 0: - c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit''', { - 'song_id': song_id, 'difficulty': difficulty, 'limit': limit}) - else: - c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC''', { - 'song_id': song_id, 'difficulty': difficulty}) - x = c.fetchall() - r = [] - if x != []: - rank = 0 - for i in x: - rank += 1 - y = get_score(c, i[0], song_id, difficulty) - y['rank'] = rank - r.append(y) - - conn.commit() - conn.close() - return r - - -def arc_score_me(user_id, song_id, difficulty, limit=20): - # 得到用户的排名,默认最大20个 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - r = [] - c.execute('''select exists(select * from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty)''', { - 'user_id': user_id, 'song_id': song_id, 'difficulty': difficulty}) - if c.fetchone() == (1,): - c.execute('''select count(*) from best_score where song_id = :song_id and difficulty = :difficulty and (score>(select score from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty) or (score>(select score from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty) and time_played > (select time_played from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty)) )''', { - 'user_id': user_id, 'song_id': song_id, 'difficulty': difficulty}) - x = c.fetchone() - myrank = int(x[0]) + 1 - if myrank <= 4: # 排名在前4 - conn.commit() - conn.close() - return arc_score_top(song_id, difficulty, limit) - elif myrank >= 5 and myrank <= 9999 - limit + 4: # 万名内,前面有4个人 - c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit offset :offset''', { - 'song_id': song_id, 'difficulty': difficulty, 'limit': limit, 'offset': myrank - 5}) - x = c.fetchall() - if x != []: - rank = myrank - 5 - for i in x: - rank += 1 - y = get_score(c, i[0], song_id, difficulty) - y['rank'] = rank - r.append(y) - - elif myrank >= 10000: # 万名外 - c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit offset :offset''', { - 'song_id': song_id, 'difficulty': difficulty, 'limit': limit - 1, 'offset': 9999-limit}) - x = c.fetchall() - if x != []: - rank = 9999 - limit - for i in x: - rank += 1 - y = get_score(c, i[0], song_id, difficulty) - y['rank'] = rank - r.append(y) - y = get_score(c, user_id, song_id, difficulty) - y['rank'] = -1 - r.append(y) - else: - c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit offset :offset''', { - 'song_id': song_id, 'difficulty': difficulty, 'limit': limit, 'offset': 9998-limit}) - x = c.fetchall() - if x != []: - rank = 9998 - limit - for i in x: - rank += 1 - y = get_score(c, i[0], song_id, difficulty) - y['rank'] = rank - r.append(y) - - conn.commit() - conn.close() - return r - - -def get_one_ptt(song_id, difficulty, score: int) -> float: - # 单曲ptt计算 - conn = sqlite3.connect('./database/arcsong.db') - c = conn.cursor() - if difficulty == 0: - c.execute('''select rating_pst from songs where sid = :sid;''', { - 'sid': song_id}) - elif difficulty == 1: - c.execute('''select rating_prs from songs where sid = :sid;''', { - 'sid': song_id}) - elif difficulty == 2: - c.execute('''select rating_ftr from songs where sid = :sid;''', { - 'sid': song_id}) - elif difficulty == 3: - c.execute('''select rating_byn from songs where sid = :sid;''', { - 'sid': song_id}) - - x = c.fetchone() - defnum = 10.0 # 没在库里的全部当做定数10.0,不过要小心recent30表可能会被污染 - if x is not None and x != '': - defnum = float(x[0]) / 10 - if defnum <= 0: - defnum = 11.0 # 缺少难度的当做定数11.0 - - if score >= 10000000: - ptt = defnum + 2 - elif score < 9800000: - ptt = defnum + (score-9500000) / 300000 - if ptt < 0: - ptt = 0 - else: - ptt = defnum + 1 + (score-9800000) / 200000 - - conn.commit() - conn.close() - return ptt - - -def get_song_grade(x): - # 成绩转换评级 - if x >= 9900000: # EX+ - return 6 - elif x < 9900000 and x >= 9800000: # EX - return 5 - elif x < 9800000 and x >= 9500000: # AA - return 4 - elif x < 9500000 and x >= 9200000: # A - return 3 - elif x < 9200000 and x >= 8900000: # B - return 2 - elif x < 8900000 and x >= 8600000: # C - return 1 - else: - return 0 - - -def get_song_state(x): - # 返回成绩状态,便于比较 - if x == 3: # PM - return 5 - elif x == 2: # FC - return 4 - elif x == 5: # Hard Clear - return 3 - elif x == 1: # Clear - return 2 - elif x == 4: # Easy Clear - return 1 - else: # Track Lost - return 0 - - -def update_recent30(c, user_id, song_id, rating): - # 刷新r30,这里的判断方法存疑 - c.execute('''select * from recent30 where user_id = :a''', {'a': user_id}) - x = c.fetchone() - songs = [] - flag = True - for i in range(2, 61, 2): - if x[i] is None or x[i] == '': - r30_id = 29 - flag = False - break - if x[i] not in songs: - songs.append(x[i]) - if flag: - n = len(song_id) - if n >= 11: - r30_id = 29 - elif song_id not in songs and n == 10: - r30_id = 29 - elif song_id in songs and n == 10: - i = 29 - while x[i*2+2] == song_id: - i -= 1 - r30_id = i - elif song_id not in songs and n == 9: - i = 29 - while x[i*2+2] == song_id: - i -= 1 - r30_id = i - else: - r30_id = 29 - a = [] - b = [] - for i in range(1, 61, 2): - a.append(x[i]) - b.append(x[i+1]) - for i in range(r30_id, 0, -1): - a[i] = a[i-1] - b[i] = b[i-1] - a[0] = rating - b[0] = song_id - c.execute('''delete from recent30 where user_id = :a''', {'a': user_id}) - sql = 'insert into recent30 values(' + str(user_id) - for i in range(0, 30): - if a[i] is not None and b[i] is not None: - sql = sql + ',' + str(a[i]) + ',"' + b[i] + '"' - else: - sql = sql + ',0,""' - - sql = sql + ')' - c.execute(sql) - return None - - -def get_user_ptt(c, user_id) -> int: - # 总ptt计算 - sumr = 0 - c.execute('''select rating from best_score where user_id = :a order by rating DESC limit 30''', { - 'a': user_id}) - x = c.fetchall() - if x != []: - n = len(x) - for i in x: - sumr += float(i[0]) - c.execute('''select * from recent30 where user_id = :a''', {'a': user_id}) - x = c.fetchone() - if x is not None: - r30 = [] - s30 = [] - for i in range(1, 61, 2): - if x[i] is not None: - r30.append(float(x[i])) - s30.append(x[i+1]) - else: - r30.append(0) - s30.append('') - r30, s30 = (list(t) for t in zip(*sorted(zip(r30, s30), reverse=True))) - songs = [] - i = 0 - while len(songs) < 10 and i <= 29 and s30[i] != '' and s30[i] is not None: - if s30[i] not in songs: - sumr += r30[i] - songs.append(s30[i]) - i += 1 - - return int(sumr/40*100) - - -def arc_score_post(user_id, song_id, difficulty, score, shiny_perfect_count, perfect_count, near_count, miss_count, health, modifier, beyond_gauge, clear_type): - # 分数上传,返回变化后的ptt,和世界模式变化 - - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - rating = get_one_ptt(song_id, difficulty, score) - now = int(time.time() * 1000) - # recent 更新 - c.execute('''update user set song_id = :b, difficulty = :c, score = :d, shiny_perfect_count = :e, perfect_count = :f, near_count = :g, miss_count = :h, health = :i, modifier = :j, clear_type = :k, rating = :l, time_played = :m where user_id = :a''', { - 'a': user_id, 'b': song_id, 'c': difficulty, 'd': score, 'e': shiny_perfect_count, 'f': perfect_count, 'g': near_count, 'h': miss_count, 'i': health, 'j': modifier, 'k': clear_type, 'l': rating, 'm': now}) - # recent30 更新 - update_recent30(c, user_id, song_id+str(difficulty), rating) - # 成绩录入 - c.execute('''select score, best_clear_type from best_score where user_id = :a and song_id = :b and difficulty = :c''', { - 'a': user_id, 'b': song_id, 'c': difficulty}) - now = int(now // 1000) - x = c.fetchone() - if x is None: - c.execute('''insert into best_score values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n)''', { - 'a': user_id, 'b': song_id, 'c': difficulty, 'd': score, 'e': shiny_perfect_count, 'f': perfect_count, 'g': near_count, 'h': miss_count, 'i': health, 'j': modifier, 'k': now, 'l': clear_type, 'm': clear_type, 'n': rating}) - else: - if get_song_state(clear_type) > get_song_state(int(x[1])): # 状态更新 - c.execute('''update best_score set best_clear_type = :a where user_id = :b and song_id = :c and difficulty = :d''', { - 'a': clear_type, 'b': user_id, 'c': song_id, 'd': difficulty}) - if score >= int(x[0]): # 成绩更新 - c.execute('''update best_score set score = :d, shiny_perfect_count = :e, perfect_count = :f, near_count = :g, miss_count = :h, health = :i, modifier = :j, clear_type = :k, rating = :l, time_played = :m where user_id = :a and song_id = :b and difficulty = :c ''', { - 'a': user_id, 'b': song_id, 'c': difficulty, 'd': score, 'e': shiny_perfect_count, 'f': perfect_count, 'g': near_count, 'h': miss_count, 'i': health, 'j': modifier, 'k': clear_type, 'l': rating, 'm': now}) - # 总PTT更新 - ptt = get_user_ptt(c, user_id) - c.execute('''update user set rating_ptt = :a where user_id = :b''', { - 'a': ptt, 'b': user_id}) - # 世界模式判断 - c.execute('''select stamina_multiply,fragment_multiply,prog_boost_multiply from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', { - 'a': user_id, 'b': song_id, 'c': difficulty}) - x = c.fetchone() - re = None - if x: - stamina_multiply = x[0] - fragment_multiply = x[1] - prog_boost_multiply = x[2] - step_times = stamina_multiply * fragment_multiply / \ - 100 * (prog_boost_multiply+100)/100 - exp_times = stamina_multiply * (prog_boost_multiply+100)/100 - c.execute('''delete from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', { - 'a': user_id, 'b': song_id, 'c': difficulty}) - c.execute('''select character_id,frag,prog,overdrive from user_char where user_id = :a and character_id = (select character_id from user where user_id=:a)''', { - 'a': user_id}) - y = c.fetchone() - if y: - character_id = y[0] - flag = float(y[1]) - prog = float(y[2]) - overdrive = float(y[3]) - else: - character_id = 0 - flag = 0 - prog = 0 - overdrive = 0 - - c.execute('''select current_map from user where user_id = :a''', { - 'a': user_id}) - map_id = c.fetchone()[0] - - if beyond_gauge == 0: # 是否是beyond挑战 - base_step = 2.5 + 2.45*rating**0.5 - step = base_step * (prog/50) * step_times - else: - info = server.arcworld.get_world_info(map_id) - if clear_type == 0: - base_step = 8/9 + (rating/1.3)**0.5 - else: - base_step = 8/3 + (rating/1.3)**0.5 - - if character_id in info['character_affinity']: - affinity_multiplier = info['affinity_multiplier'][info['character_affinity'].index( - character_id)] - else: - affinity_multiplier = 1 - - step = base_step * (prog/50) * step_times * affinity_multiplier - - c.execute('''select * from user_world where user_id = :a and map_id =:b''', - {'a': user_id, 'b': map_id}) - y = c.fetchone() - rewards, steps, curr_position, curr_capture, info = server.arcworld.climb_step( - user_id, map_id, step, y[3], y[2]) - - if beyond_gauge == 0: - re = { - "rewards": rewards, - "exp": 25000, - "level": 30, - "base_progress": base_step, - "progress": step, - "user_map": { - "user_id": user_id, - "curr_position": curr_position, - "curr_capture": curr_capture, - "is_locked": int2b(y[4]), - "map_id": map_id, - "prev_capture": y[3], - "prev_position": y[2], - "beyond_health": info['beyond_health'], - "steps": steps - }, - "char_stats": { - "character_id": character_id, - "frag": flag, - "prog": prog, - "overdrive": overdrive - }, - "current_stamina": 12, - "max_stamina_ts": 1586274871917, - "user_rating": ptt - } - else: - re = { - "rewards": rewards, - "exp": 25000, - "level": 30, - "base_progress": base_step, - "progress": step, - "user_map": { - "user_id": user_id, - "curr_position": curr_position, - "curr_capture": curr_capture, - "is_locked": int2b(y[4]), - "map_id": map_id, - "prev_capture": y[3], - "prev_position": y[2], - "beyond_health": info['beyond_health'], - "step_count": len(steps) - }, - "char_stats": { - "character_id": character_id, - "frag": flag, - "prog": prog, - "overdrive": overdrive - }, - "current_stamina": 12, - "max_stamina_ts": 1586274871917, - "user_rating": ptt - } - - if stamina_multiply != 1: - re['stamina_multiply'] = stamina_multiply - if fragment_multiply != 100: - re['fragment_multiply'] = fragment_multiply - if prog_boost_multiply != 0: - re['prog_boost_multiply'] = prog_boost_multiply - - if curr_position == info['step_count']-1 and info['is_repeatable']: # 循环图判断 - curr_position = 0 - c.execute('''update user_world set curr_position=:a, curr_capture=:b where user_id=:c and map_id=:d''', { - 'a': curr_position, 'b': curr_capture, 'c': user_id, 'd': map_id}) - conn.commit() - conn.close() - return ptt, re - - -def arc_all_post(user_id, scores_data, clearlamps_data): - # 向云端同步,无返回 - # 注意,best_score表不比较,直接覆盖 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - scores = json.loads(scores_data)[""] - clearlamps = json.loads(clearlamps_data)[""] - clear_song_id_difficulty = [] - clear_state = [] - for i in clearlamps: - clear_song_id_difficulty.append(i['song_id']+str(i['difficulty'])) - clear_state.append(i['clear_type']) - - for i in scores: - rating = get_one_ptt(i['song_id'], i['difficulty'], i['score']) - try: - index = clear_song_id_difficulty.index( - i['song_id'] + str(i['difficulty'])) - except: - index = -1 - if index != -1: - clear_type = clear_state[index] - else: - clear_type = 0 - c.execute('''delete from best_score where user_id = :a and song_id = :b and difficulty = :c''', { - 'a': user_id, 'b': i['song_id'], 'c': i['difficulty']}) - c.execute('''insert into best_score values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n)''', { - 'a': user_id, 'b': i['song_id'], 'c': i['difficulty'], 'd': i['score'], 'e': i['shiny_perfect_count'], 'f': i['perfect_count'], 'g': i['near_count'], 'h': i['miss_count'], 'i': i['health'], 'j': i['modifier'], 'k': i['time_played'], 'l': clear_type, 'm': clear_type, 'n': rating}) - - ptt = get_user_ptt(c, user_id) # 更新PTT - c.execute('''update user set rating_ptt = :a where user_id = :b''', { - 'a': ptt, 'b': user_id}) - conn.commit() - conn.close() - return None - - -def arc_all_get(user_id): - # 从云端同步,返回字典 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - c.execute('''select * from best_score where user_id = :a''', - {'a': user_id}) - x = c.fetchall() - song_1 = [] - song_2 = [] - song_3 = [] - if x != []: - for i in x: - if i[11] != 0: - song_1.append({ - "grade": get_song_grade(i[3]), - "difficulty": i[2], - "song_id": i[1] - }) - song_2.append({ - "ct": 0, - "clear_type": i[11], - "difficulty": i[2], - "song_id": i[1] - }) - song_3.append({ - "ct": 0, - "time_played": i[10], - "modifier": i[9], - "health": i[8], - "miss_count": i[7], - "near_count": i[6], - "perfect_count": i[5], - "shiny_perfect_count": i[4], - "score": i[3], - "difficulty": i[2], - "version": 1, - "song_id": i[1] - }) - - conn.commit() - conn.close() - return { - "user_id": user_id, - "story": { - "": [{ - "r": True, - "c": True, - "mi": 1, - "ma": 1 - }, { - "r": True, - "c": True, - "mi": 2, - "ma": 1 - }, { - "r": True, - "c": True, - "mi": 3, - "ma": 1 - }, { - "r": True, - "c": True, - "mi": 4, - "ma": 1 - }, { - "r": True, - "c": True, - "mi": 5, - "ma": 1 - }, { - "r": True, - "c": True, - "mi": 6, - "ma": 1 - }, { - "r": True, - "c": True, - "mi": 7, - "ma": 1 - }, { - "r": True, - "c": True, - "mi": 8, - "ma": 1 - }, { - "r": True, - "c": True, - "mi": 9, - "ma": 1 - }, { - "r": True, - "c": True, - "mi": 1, - "ma": 2 - }, { - "r": True, - "c": True, - "mi": 2, - "ma": 2 - }, { - "r": True, - "c": True, - "mi": 3, - "ma": 2 - }, { - "r": True, - "c": True, - "mi": 4, - "ma": 2 - }, { - "r": True, - "c": True, - "mi": 5, - "ma": 2 - }, { - "r": True, - "c": True, - "mi": 6, - "ma": 2 - }, { - "r": True, - "c": True, - "mi": 7, - "ma": 2 - }, { - "r": True, - "c": True, - "mi": 8, - "ma": 2 - }, { - "r": True, - "c": True, - "mi": 9, - "ma": 2 - }, { - "r": True, - "c": True, - "mi": 1, - "ma": 100 - }, { - "r": True, - "c": True, - "mi": 2, - "ma": 100 - }, { - "r": True, - "c": True, - "mi": 3, - "ma": 100 - }, { - "r": True, - "c": True, - "mi": 4, - "ma": 100 - }, { - "r": True, - "c": True, - "mi": 5, - "ma": 100 - }, { - "r": True, - "c": True, - "mi": 1, - "ma": 101 - }, { - "r": True, - "c": True, - "mi": 2, - "ma": 101 - }, { - "r": True, - "c": True, - "mi": 3, - "ma": 101 - }, { - "r": True, - "c": True, - "mi": 4, - "ma": 101 - }, { - "r": True, - "c": True, - "mi": 5, - "ma": 101 - }, { - "r": True, - "c": True, - "mi": 6, - "ma": 101 - }, { - "r": True, - "c": True, - "mi": 7, - "ma": 101 - }, { - "r": True, - "c": True, - "mi": 8, - "ma": 101 - }, { - "r": True, - "c": True, - "mi": 1, - "ma": 3 - }, { - "r": True, - "c": True, - "mi": 2, - "ma": 3 - }, { - "r": True, - "c": True, - "mi": 3, - "ma": 3 - }, { - "r": True, - "c": True, - "mi": 4, - "ma": 3 - }, { - "r": True, - "c": True, - "mi": 5, - "ma": 3 - }, { - "r": True, - "c": True, - "mi": 6, - "ma": 3 - }, { - "r": True, - "c": True, - "mi": 1, - "ma": 4 - }, { - "r": True, - "c": True, - "mi": 2, - "ma": 4 - }, { - "r": True, - "c": True, - "mi": 3, - "ma": 4 - }, { - "r": True, - "c": True, - "mi": 4, - "ma": 4 - }, { - "r": True, - "c": True, - "mi": 5, - "ma": 4 - }, { - "r": True, - "c": True, - "mi": 6, - "ma": 4 - }, { - "r": True, - "c": True, - "mi": 7, - "ma": 4 - }, { - "r": True, - "c": True, - "mi": 8, - "ma": 4 - }, { - "r": True, - "c": True, - "mi": 1, - "ma": 5 - }, { - "r": True, - "c": True, - "mi": 2, - "ma": 5 - }, { - "r": True, - "c": True, - "mi": 3, - "ma": 5 - }, { - "r": True, - "c": True, - "mi": 4, - "ma": 5 - }, { - "r": True, - "c": True, - "mi": 5, - "ma": 5 - }, { - "r": True, - "c": True, - "mi": 6, - "ma": 5 - }, { - "r": True, - "c": True, - "mi": 1, - "ma": 6 - }, { - "r": True, - "c": True, - "mi": 2, - "ma": 6 - }, { - "r": True, - "c": True, - "mi": 3, - "ma": 6 - }] - }, - "devicemodelname": { - "val": "MopeMope" - }, - "installid": { - "val": "b5e064cf-1a3f-4e64-9636-fce4accc9011" - }, - "unlocklist": { - "": [{ - "complete": 1, - "unlock_key": "worldvanquisher|2|0" - }, { - "complete": 1, - "unlock_key": "worldvanquisher|1|0" - }, { - "complete": 1, - "unlock_key": "worldexecuteme|2|0" - }, { - "complete": 1, - "unlock_key": "viciousheroism|2|0" - }, { - "complete": 1, - "unlock_key": "vector|2|0" - }, { - "complete": 1, - "unlock_key": "valhallazero|2|0" - }, { - "complete": 1, - "unlock_key": "tiferet|1|0" - }, { - "complete": 1, - "unlock_key": "tiemedowngently|1|0" - }, { - "complete": 1, - "unlock_key": "tempestissimo|0|101" - }, { - "complete": 1, - "unlock_key": "syro|2|0" - }, { - "complete": 1, - "unlock_key": "suomi|1|0" - }, { - "complete": 1, - "unlock_key": "solitarydream|2|0" - }, { - "complete": 1, - "unlock_key": "snowwhite|2|0" - }, { - "complete": 1, - "unlock_key": "sheriruth|2|0" - }, { - "complete": 1, - "unlock_key": "senkyou|2|0" - }, { - "complete": 1, - "unlock_key": "senkyou|1|0" - }, { - "complete": 1, - "unlock_key": "scarletlance|2|0" - }, { - "complete": 1, - "unlock_key": "scarletlance|1|0" - }, { - "complete": 1, - "unlock_key": "rugie|2|0" - }, { - "complete": 1, - "unlock_key": "rugie|1|0" - }, { - "complete": 1, - "unlock_key": "rise|2|0" - }, { - "complete": 1, - "unlock_key": "revixy|2|0" - }, { - "complete": 1, - "unlock_key": "reinvent|2|0" - }, { - "complete": 1, - "unlock_key": "reinvent|1|0" - }, { - "complete": 1, - "unlock_key": "redandblue|2|0" - }, { - "complete": 1, - "unlock_key": "redandblue|1|0" - }, { - "complete": 1, - "unlock_key": "rabbitintheblackroom|2|0" - }, { - "complete": 1, - "unlock_key": "rabbitintheblackroom|1|0" - }, { - "complete": 1, - "unlock_key": "worldexecuteme|1|0" - }, { - "complete": 1, - "unlock_key": "ringedgenesis|2|0" - }, { - "complete": 1, - "unlock_key": "quon|1|0" - }, { - "complete": 1, - "unlock_key": "qualia|2|0" - }, { - "complete": 1, - "unlock_key": "purgatorium|2|0" - }, { - "complete": 1, - "unlock_key": "supernova|2|0" - }, { - "complete": 1, - "unlock_key": "saikyostronger|2|3|einherjar|2" - }, { - "complete": 1, - "unlock_key": "purgatorium|1|0" - }, { - "complete": 1, - "unlock_key": "pragmatism|2|0" - }, { - "complete": 1, - "unlock_key": "ouroboros|2|0" - }, { - "complete": 1, - "unlock_key": "ouroboros|1|0" - }, { - "complete": 1, - "unlock_key": "oracle|1|0" - }, { - "complete": 1, - "unlock_key": "onelastdrive|2|0" - }, { - "complete": 1, - "unlock_key": "onelastdrive|1|0" - }, { - "complete": 1, - "unlock_key": "oblivia|2|0" - }, { - "complete": 1, - "unlock_key": "memoryforest|1|0" - }, { - "complete": 1, - "unlock_key": "melodyoflove|2|0" - }, { - "complete": 1, - "unlock_key": "saikyostronger|2|3|laqryma|2" - }, { - "complete": 1, - "unlock_key": "melodyoflove|1|0" - }, { - "complete": 1, - "unlock_key": "lucifer|2|0" - }, { - "complete": 1, - "unlock_key": "saikyostronger|2|3|izana|2" - }, { - "complete": 1, - "unlock_key": "halcyon|1|0" - }, { - "complete": 1, - "unlock_key": "memoryforest|2|0" - }, { - "complete": 1, - "unlock_key": "tiemedowngently|2|0" - }, { - "complete": 1, - "unlock_key": "lostdesire|1|0" - }, { - "complete": 1, - "unlock_key": "viciousheroism|1|0" - }, { - "complete": 1, - "unlock_key": "flyburg|1|0" - }, { - "complete": 1, - "unlock_key": "lostcivilization|2|0" - }, { - "complete": 1, - "unlock_key": "infinityheaven|1|0" - }, { - "complete": 1, - "unlock_key": "lostdesire|2|0" - }, { - "complete": 1, - "unlock_key": "ignotus|2|0" - }, { - "complete": 1, - "unlock_key": "harutopia|2|0" - }, { - "complete": 1, - "unlock_key": "revixy|1|0" - }, { - "complete": 1, - "unlock_key": "aterlbus|1|0" - }, { - "complete": 1, - "unlock_key": "linearaccelerator|2|0" - }, { - "complete": 1, - "unlock_key": "guardina|2|0" - }, { - "complete": 1, - "unlock_key": "corpssansorganes|2|0" - }, { - "complete": 1, - "unlock_key": "linearaccelerator|1|0" - }, { - "complete": 1, - "unlock_key": "guardina|1|0" - }, { - "complete": 1, - "unlock_key": "saikyostronger|2|0" - }, { - "complete": 1, - "unlock_key": "guardina|0|0" - }, { - "complete": 1, - "unlock_key": "valhallazero|1|0" - }, { - "complete": 1, - "unlock_key": "grimheart|1|0" - }, { - "complete": 1, - "unlock_key": "blaster|2|0" - }, { - "complete": 1, - "unlock_key": "grievouslady|2|101" - }, { - "complete": 1, - "unlock_key": "partyvinyl|2|0" - }, { - "complete": 1, - "unlock_key": "darakunosono|1|0" - }, { - "complete": 1, - "unlock_key": "grievouslady|1|101" - }, { - "complete": 1, - "unlock_key": "goodtek|1|0" - }, { - "complete": 1, - "unlock_key": "tempestissimo|3|101" - }, { - "complete": 1, - "unlock_key": "chronostasis|2|0" - }, { - "complete": 1, - "unlock_key": "gloryroad|2|0" - }, { - "complete": 1, - "unlock_key": "supernova|1|0" - }, { - "complete": 1, - "unlock_key": "singularity|2|0" - }, { - "complete": 1, - "unlock_key": "gloryroad|0|0" - }, { - "complete": 1, - "unlock_key": "shadesoflight|1|0" - }, { - "complete": 1, - "unlock_key": "kanagawa|2|0" - }, { - "complete": 1, - "unlock_key": "genesis|1|0" - }, { - "complete": 1, - "unlock_key": "fractureray|1|101" - }, { - "complete": 1, - "unlock_key": "freefall|2|0" - }, { - "complete": 1, - "unlock_key": "babaroque|1|0" - }, { - "complete": 1, - "unlock_key": "monochromeprincess|2|0" - }, { - "complete": 1, - "unlock_key": "flyburg|2|0" - }, { - "complete": 1, - "unlock_key": "shadesoflight|2|0" - }, { - "complete": 1, - "unlock_key": "espebranch|2|0" - }, { - "complete": 1, - "unlock_key": "qualia|1|0" - }, { - "complete": 1, - "unlock_key": "etherstrike|2|0" - }, { - "complete": 1, - "unlock_key": "tempestissimo|1|101" - }, { - "complete": 1, - "unlock_key": "conflict|1|0" - }, { - "complete": 1, - "unlock_key": "nhelv|1|0" - }, { - "complete": 1, - "unlock_key": "etherstrike|1|0" - }, { - "complete": 1, - "unlock_key": "syro|1|0" - }, { - "complete": 1, - "unlock_key": "anokumene|2|0" - }, { - "complete": 1, - "unlock_key": "essenceoftwilight|2|0" - }, { - "complete": 1, - "unlock_key": "snowwhite|1|0" - }, { - "complete": 1, - "unlock_key": "partyvinyl|1|0" - }, { - "complete": 1, - "unlock_key": "axiumcrisis|1|0" - }, { - "complete": 1, - "unlock_key": "ifi|2|0" - }, { - "complete": 1, - "unlock_key": "espebranch|1|0" - }, { - "complete": 1, - "unlock_key": "lostcivilization|1|0" - }, { - "complete": 1, - "unlock_key": "goodtek|2|0" - }, { - "complete": 1, - "unlock_key": "dandelion|2|0" - }, { - "complete": 1, - "unlock_key": "suomi|2|0" - }, { - "complete": 1, - "unlock_key": "dandelion|1|0" - }, { - "complete": 1, - "unlock_key": "oblivia|1|0" - }, { - "complete": 1, - "unlock_key": "cyberneciacatharsis|1|0" - }, { - "complete": 1, - "unlock_key": "quon|2|0" - }, { - "complete": 1, - "unlock_key": "bookmaker|2|0" - }, { - "complete": 1, - "unlock_key": "chronostasis|1|0" - }, { - "complete": 1, - "unlock_key": "heavensdoor|1|0" - }, { - "complete": 1, - "unlock_key": "tempestissimo|2|101" - }, { - "complete": 1, - "unlock_key": "cyaegha|2|0" - }, { - "complete": 1, - "unlock_key": "axiumcrisis|2|0" - }, { - "complete": 1, - "unlock_key": "blrink|2|0" - }, { - "complete": 1, - "unlock_key": "rise|1|0" - }, { - "complete": 1, - "unlock_key": "cyanine|1|0" - }, { - "complete": 1, - "unlock_key": "ifi|1|0" - }, { - "complete": 1, - "unlock_key": "aterlbus|2|0" - }, { - "complete": 1, - "unlock_key": "dreaminattraction|2|0" - }, { - "complete": 1, - "unlock_key": "bookmaker|1|0" - }, { - "complete": 1, - "unlock_key": "lucifer|1|0" - }, { - "complete": 1, - "unlock_key": "solitarydream|1|0" - }, { - "complete": 1, - "unlock_key": "ringedgenesis|1|0" - }, { - "complete": 1, - "unlock_key": "corpssansorganes|1|0" - }, { - "complete": 1, - "unlock_key": "vector|1|0" - }, { - "complete": 1, - "unlock_key": "infinityheaven|2|0" - }, { - "complete": 1, - "unlock_key": "essenceoftwilight|1|0" - }, { - "complete": 1, - "unlock_key": "conflict|2|0" - }, { - "complete": 1, - "unlock_key": "singularity|1|0" - }, { - "complete": 1, - "unlock_key": "harutopia|1|0" - }, { - "complete": 1, - "unlock_key": "cyberneciacatharsis|2|0" - }, { - "complete": 1, - "unlock_key": "oracle|2|0" - }, { - "complete": 1, - "unlock_key": "clotho|2|0" - }, { - "complete": 1, - "unlock_key": "corpssansorganes|0|0" - }, { - "complete": 1, - "unlock_key": "ignotus|1|0" - }, { - "complete": 1, - "unlock_key": "monochromeprincess|1|0" - }, { - "complete": 1, - "unlock_key": "nirvluce|1|0" - }, { - "complete": 1, - "unlock_key": "lethaeus|1|0" - }, { - "complete": 1, - "unlock_key": "clotho|1|0" - }, { - "complete": 1, - "unlock_key": "blaster|1|0" - }, { - "complete": 1, - "unlock_key": "fractureray|0|101" - }, { - "complete": 1, - "unlock_key": "kanagawa|1|0" - }, { - "complete": 1, - "unlock_key": "darakunosono|2|0" - }, { - "complete": 1, - "unlock_key": "freefall|1|0" - }, { - "complete": 1, - "unlock_key": "nirvluce|2|0" - }, { - "complete": 1, - "unlock_key": "cyanine|2|0" - }, { - "complete": 1, - "unlock_key": "heavensdoor|2|0" - }, { - "complete": 1, - "unlock_key": "genesis|2|0" - }, { - "complete": 1, - "unlock_key": "pragmatism|1|0" - }, { - "complete": 1, - "unlock_key": "nhelv|2|0" - }, { - "complete": 1, - "unlock_key": "halcyon|2|0" - }, { - "complete": 1, - "unlock_key": "blrink|1|0" - }, { - "complete": 1, - "unlock_key": "fractureray|2|101" - }, { - "complete": 1, - "unlock_key": "lethaeus|2|0" - }, { - "complete": 1, - "unlock_key": "sheriruth|1|0" - }, { - "complete": 1, - "unlock_key": "babaroque|2|0" - }, { - "complete": 1, - "unlock_key": "tiferet|2|0" - }, { - "complete": 1, - "unlock_key": "grimheart|2|0" - }, { - "complete": 1, - "unlock_key": "cyaegha|1|0" - }, { - "complete": 1, - "unlock_key": "aiueoon|2|0" - }, { - "complete": 1, - "unlock_key": "gloryroad|1|0" - }, { - "complete": 1, - "unlock_key": "anokumene|1|0" - }, { - "complete": 1, - "unlock_key": "grievouslady|0|101" - }, { - "complete": 1, - "unlock_key": "dreaminattraction|1|0" - }] - }, "clearedsongs": { - "": song_1 - }, - "clearlamps": { - "": song_2 - }, - "scores": { - "": song_3 - }, - "version": { - "val": 1 - } - } +import sqlite3 +import time +import json +import server.arcworld + + +def b2int(x): + # int与布尔值转换 + if x: + return 1 + else: + return 0 + + +def int2b(x): + # int与布尔值转换 + if x is None or x == 0: + return False + else: + return True + + +def get_score(c, user_id, song_id, difficulty): + # 根据user_id、song_id、难度得到该曲目最好成绩,返回字典 + c.execute('''select * from best_score where user_id = :a and song_id = :b and difficulty = :c''', + {'a': user_id, 'b': song_id, 'c': difficulty}) + x = c.fetchone() + if x is not None: + c.execute('''select name, character_id, is_skill_sealed, is_char_uncapped from user where user_id = :a''', { + 'a': user_id}) + y = c.fetchone() + if y is not None: + return { + "user_id": x[0], + "song_id": x[1], + "difficulty": x[2], + "score": x[3], + "shiny_perfect_count": x[4], + "perfect_count": x[5], + "near_count": x[6], + "miss_count": x[7], + "health": x[8], + "modifier": x[9], + "time_played": x[10], + "best_clear_type": x[11], + "clear_type": x[12], + "name": y[0], + "character": y[1], + "is_skill_sealed": int2b(y[2]), + "is_char_uncapped": int2b(y[3]) + } + else: + return {} + else: + return {} + + +def arc_score_friend(user_id, song_id, difficulty, limit=50): + # 得到用户好友分数表,默认最大50个 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select user_id from best_score where user_id in (select :user_id union select user_id_other from friend where user_id_me = :user_id) and song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit''', { + 'user_id': user_id, 'song_id': song_id, 'difficulty': difficulty, 'limit': limit}) + x = c.fetchall() + r = [] + if x != []: + rank = 0 + for i in x: + rank += 1 + y = get_score(c, i[0], song_id, difficulty) + y['rank'] = rank + r.append(y) + + conn.commit() + conn.close() + return r + + +def arc_score_top(song_id, difficulty, limit=20): + # 得到top分数表,默认最多20个,如果是负数则全部查询 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + if limit >= 0: + c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit''', { + 'song_id': song_id, 'difficulty': difficulty, 'limit': limit}) + else: + c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC''', { + 'song_id': song_id, 'difficulty': difficulty}) + x = c.fetchall() + r = [] + if x != []: + rank = 0 + for i in x: + rank += 1 + y = get_score(c, i[0], song_id, difficulty) + y['rank'] = rank + r.append(y) + + conn.commit() + conn.close() + return r + + +def arc_score_me(user_id, song_id, difficulty, limit=20): + # 得到用户的排名,默认最大20个 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + r = [] + c.execute('''select exists(select * from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty)''', { + 'user_id': user_id, 'song_id': song_id, 'difficulty': difficulty}) + if c.fetchone() == (1,): + c.execute('''select count(*) from best_score where song_id = :song_id and difficulty = :difficulty and (score>(select score from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty) or (score>(select score from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty) and time_played > (select time_played from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty)) )''', { + 'user_id': user_id, 'song_id': song_id, 'difficulty': difficulty}) + x = c.fetchone() + myrank = int(x[0]) + 1 + if myrank <= 4: # 排名在前4 + conn.commit() + conn.close() + return arc_score_top(song_id, difficulty, limit) + elif myrank >= 5 and myrank <= 9999 - limit + 4: # 万名内,前面有4个人 + c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit offset :offset''', { + 'song_id': song_id, 'difficulty': difficulty, 'limit': limit, 'offset': myrank - 5}) + x = c.fetchall() + if x != []: + rank = myrank - 5 + for i in x: + rank += 1 + y = get_score(c, i[0], song_id, difficulty) + y['rank'] = rank + r.append(y) + + elif myrank >= 10000: # 万名外 + c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit offset :offset''', { + 'song_id': song_id, 'difficulty': difficulty, 'limit': limit - 1, 'offset': 9999-limit}) + x = c.fetchall() + if x != []: + rank = 9999 - limit + for i in x: + rank += 1 + y = get_score(c, i[0], song_id, difficulty) + y['rank'] = rank + r.append(y) + y = get_score(c, user_id, song_id, difficulty) + y['rank'] = -1 + r.append(y) + else: + c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit offset :offset''', { + 'song_id': song_id, 'difficulty': difficulty, 'limit': limit, 'offset': 9998-limit}) + x = c.fetchall() + if x != []: + rank = 9998 - limit + for i in x: + rank += 1 + y = get_score(c, i[0], song_id, difficulty) + y['rank'] = rank + r.append(y) + + conn.commit() + conn.close() + return r + + +def get_one_ptt(song_id, difficulty, score: int) -> float: + # 单曲ptt计算 + conn = sqlite3.connect('./database/arcsong.db') + c = conn.cursor() + if difficulty == 0: + c.execute('''select rating_pst from songs where sid = :sid;''', { + 'sid': song_id}) + elif difficulty == 1: + c.execute('''select rating_prs from songs where sid = :sid;''', { + 'sid': song_id}) + elif difficulty == 2: + c.execute('''select rating_ftr from songs where sid = :sid;''', { + 'sid': song_id}) + elif difficulty == 3: + c.execute('''select rating_byn from songs where sid = :sid;''', { + 'sid': song_id}) + + x = c.fetchone() + defnum = 10.0 # 没在库里的全部当做定数10.0,不过要小心recent30表可能会被污染 + if x is not None and x != '': + defnum = float(x[0]) / 10 + if defnum <= 0: + defnum = 11.0 # 缺少难度的当做定数11.0 + + if score >= 10000000: + ptt = defnum + 2 + elif score < 9800000: + ptt = defnum + (score-9500000) / 300000 + if ptt < 0: + ptt = 0 + else: + ptt = defnum + 1 + (score-9800000) / 200000 + + conn.commit() + conn.close() + return ptt + + +def get_song_grade(x): + # 成绩转换评级 + if x >= 9900000: # EX+ + return 6 + elif x < 9900000 and x >= 9800000: # EX + return 5 + elif x < 9800000 and x >= 9500000: # AA + return 4 + elif x < 9500000 and x >= 9200000: # A + return 3 + elif x < 9200000 and x >= 8900000: # B + return 2 + elif x < 8900000 and x >= 8600000: # C + return 1 + else: + return 0 + + +def get_song_state(x): + # 返回成绩状态,便于比较 + if x == 3: # PM + return 5 + elif x == 2: # FC + return 4 + elif x == 5: # Hard Clear + return 3 + elif x == 1: # Clear + return 2 + elif x == 4: # Easy Clear + return 1 + else: # Track Lost + return 0 + + +def update_recent30(c, user_id, song_id, rating): + # 刷新r30,这里的判断方法存疑 + c.execute('''select * from recent30 where user_id = :a''', {'a': user_id}) + x = c.fetchone() + songs = [] + flag = True + for i in range(2, 61, 2): + if x[i] is None or x[i] == '': + r30_id = 29 + flag = False + break + if x[i] not in songs: + songs.append(x[i]) + if flag: + n = len(song_id) + if n >= 11: + r30_id = 29 + elif song_id not in songs and n == 10: + r30_id = 29 + elif song_id in songs and n == 10: + i = 29 + while x[i*2+2] == song_id: + i -= 1 + r30_id = i + elif song_id not in songs and n == 9: + i = 29 + while x[i*2+2] == song_id: + i -= 1 + r30_id = i + else: + r30_id = 29 + a = [] + b = [] + for i in range(1, 61, 2): + a.append(x[i]) + b.append(x[i+1]) + for i in range(r30_id, 0, -1): + a[i] = a[i-1] + b[i] = b[i-1] + a[0] = rating + b[0] = song_id + c.execute('''delete from recent30 where user_id = :a''', {'a': user_id}) + sql = 'insert into recent30 values(' + str(user_id) + for i in range(0, 30): + if a[i] is not None and b[i] is not None: + sql = sql + ',' + str(a[i]) + ',"' + b[i] + '"' + else: + sql = sql + ',0,""' + + sql = sql + ')' + c.execute(sql) + return None + + +def get_user_ptt(c, user_id) -> int: + # 总ptt计算 + sumr = 0 + c.execute('''select rating from best_score where user_id = :a order by rating DESC limit 30''', { + 'a': user_id}) + x = c.fetchall() + if x != []: + n = len(x) + for i in x: + sumr += float(i[0]) + c.execute('''select * from recent30 where user_id = :a''', {'a': user_id}) + x = c.fetchone() + if x is not None: + r30 = [] + s30 = [] + for i in range(1, 61, 2): + if x[i] is not None: + r30.append(float(x[i])) + s30.append(x[i+1]) + else: + r30.append(0) + s30.append('') + r30, s30 = (list(t) for t in zip(*sorted(zip(r30, s30), reverse=True))) + songs = [] + i = 0 + while len(songs) < 10 and i <= 29 and s30[i] != '' and s30[i] is not None: + if s30[i] not in songs: + sumr += r30[i] + songs.append(s30[i]) + i += 1 + + return int(sumr/40*100) + + +def arc_score_post(user_id, song_id, difficulty, score, shiny_perfect_count, perfect_count, near_count, miss_count, health, modifier, beyond_gauge, clear_type): + # 分数上传,返回变化后的ptt,和世界模式变化 + + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + rating = get_one_ptt(song_id, difficulty, score) + now = int(time.time() * 1000) + # recent 更新 + c.execute('''update user set song_id = :b, difficulty = :c, score = :d, shiny_perfect_count = :e, perfect_count = :f, near_count = :g, miss_count = :h, health = :i, modifier = :j, clear_type = :k, rating = :l, time_played = :m where user_id = :a''', { + 'a': user_id, 'b': song_id, 'c': difficulty, 'd': score, 'e': shiny_perfect_count, 'f': perfect_count, 'g': near_count, 'h': miss_count, 'i': health, 'j': modifier, 'k': clear_type, 'l': rating, 'm': now}) + # recent30 更新 + update_recent30(c, user_id, song_id+str(difficulty), rating) + # 成绩录入 + c.execute('''select score, best_clear_type from best_score where user_id = :a and song_id = :b and difficulty = :c''', { + 'a': user_id, 'b': song_id, 'c': difficulty}) + now = int(now // 1000) + x = c.fetchone() + if x is None: + c.execute('''insert into best_score values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n)''', { + 'a': user_id, 'b': song_id, 'c': difficulty, 'd': score, 'e': shiny_perfect_count, 'f': perfect_count, 'g': near_count, 'h': miss_count, 'i': health, 'j': modifier, 'k': now, 'l': clear_type, 'm': clear_type, 'n': rating}) + else: + if get_song_state(clear_type) > get_song_state(int(x[1])): # 状态更新 + c.execute('''update best_score set best_clear_type = :a where user_id = :b and song_id = :c and difficulty = :d''', { + 'a': clear_type, 'b': user_id, 'c': song_id, 'd': difficulty}) + if score >= int(x[0]): # 成绩更新 + c.execute('''update best_score set score = :d, shiny_perfect_count = :e, perfect_count = :f, near_count = :g, miss_count = :h, health = :i, modifier = :j, clear_type = :k, rating = :l, time_played = :m where user_id = :a and song_id = :b and difficulty = :c ''', { + 'a': user_id, 'b': song_id, 'c': difficulty, 'd': score, 'e': shiny_perfect_count, 'f': perfect_count, 'g': near_count, 'h': miss_count, 'i': health, 'j': modifier, 'k': clear_type, 'l': rating, 'm': now}) + # 总PTT更新 + ptt = get_user_ptt(c, user_id) + c.execute('''update user set rating_ptt = :a where user_id = :b''', { + 'a': ptt, 'b': user_id}) + # 世界模式判断 + c.execute('''select stamina_multiply,fragment_multiply,prog_boost_multiply from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', { + 'a': user_id, 'b': song_id, 'c': difficulty}) + x = c.fetchone() + re = None + if x: + stamina_multiply = x[0] + fragment_multiply = x[1] + prog_boost_multiply = x[2] + step_times = stamina_multiply * fragment_multiply / \ + 100 * (prog_boost_multiply+100)/100 + exp_times = stamina_multiply * (prog_boost_multiply+100)/100 + c.execute('''delete from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', { + 'a': user_id, 'b': song_id, 'c': difficulty}) + c.execute('''select character_id,frag,prog,overdrive from user_char where user_id = :a and character_id = (select character_id from user where user_id=:a)''', { + 'a': user_id}) + y = c.fetchone() + if y: + character_id = y[0] + flag = float(y[1]) + prog = float(y[2]) + overdrive = float(y[3]) + else: + character_id = 0 + flag = 0 + prog = 0 + overdrive = 0 + + c.execute('''select current_map from user where user_id = :a''', { + 'a': user_id}) + map_id = c.fetchone()[0] + + if beyond_gauge == 0: # 是否是beyond挑战 + base_step = 2.5 + 2.45*rating**0.5 + step = base_step * (prog/50) * step_times + else: + info = server.arcworld.get_world_info(map_id) + if clear_type == 0: + base_step = 8/9 + (rating/1.3)**0.5 + else: + base_step = 8/3 + (rating/1.3)**0.5 + + if character_id in info['character_affinity']: + affinity_multiplier = info['affinity_multiplier'][info['character_affinity'].index( + character_id)] + else: + affinity_multiplier = 1 + + step = base_step * (prog/50) * step_times * affinity_multiplier + + c.execute('''select * from user_world where user_id = :a and map_id =:b''', + {'a': user_id, 'b': map_id}) + y = c.fetchone() + rewards, steps, curr_position, curr_capture, info = server.arcworld.climb_step( + user_id, map_id, step, y[3], y[2]) + + if beyond_gauge == 0: + re = { + "rewards": rewards, + "exp": 25000, + "level": 30, + "base_progress": base_step, + "progress": step, + "user_map": { + "user_id": user_id, + "curr_position": curr_position, + "curr_capture": curr_capture, + "is_locked": int2b(y[4]), + "map_id": map_id, + "prev_capture": y[3], + "prev_position": y[2], + "beyond_health": info['beyond_health'], + "steps": steps + }, + "char_stats": { + "character_id": character_id, + "frag": flag, + "prog": prog, + "overdrive": overdrive + }, + "current_stamina": 12, + "max_stamina_ts": 1586274871917, + "user_rating": ptt + } + else: + re = { + "rewards": rewards, + "exp": 25000, + "level": 30, + "base_progress": base_step, + "progress": step, + "user_map": { + "user_id": user_id, + "curr_position": curr_position, + "curr_capture": curr_capture, + "is_locked": int2b(y[4]), + "map_id": map_id, + "prev_capture": y[3], + "prev_position": y[2], + "beyond_health": info['beyond_health'], + "step_count": len(steps) + }, + "char_stats": { + "character_id": character_id, + "frag": flag, + "prog": prog, + "overdrive": overdrive + }, + "current_stamina": 12, + "max_stamina_ts": 1586274871917, + "user_rating": ptt + } + + if stamina_multiply != 1: + re['stamina_multiply'] = stamina_multiply + if fragment_multiply != 100: + re['fragment_multiply'] = fragment_multiply + if prog_boost_multiply != 0: + re['prog_boost_multiply'] = prog_boost_multiply + + if curr_position == info['step_count']-1 and info['is_repeatable']: # 循环图判断 + curr_position = 0 + c.execute('''update user_world set curr_position=:a, curr_capture=:b where user_id=:c and map_id=:d''', { + 'a': curr_position, 'b': curr_capture, 'c': user_id, 'd': map_id}) + conn.commit() + conn.close() + return ptt, re + + +def arc_all_post(user_id, scores_data, clearlamps_data): + # 向云端同步,无返回 + # 注意,best_score表不比较,直接覆盖 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + scores = json.loads(scores_data)[""] + clearlamps = json.loads(clearlamps_data)[""] + clear_song_id_difficulty = [] + clear_state = [] + for i in clearlamps: + clear_song_id_difficulty.append(i['song_id']+str(i['difficulty'])) + clear_state.append(i['clear_type']) + + for i in scores: + rating = get_one_ptt(i['song_id'], i['difficulty'], i['score']) + try: + index = clear_song_id_difficulty.index( + i['song_id'] + str(i['difficulty'])) + except: + index = -1 + if index != -1: + clear_type = clear_state[index] + else: + clear_type = 0 + c.execute('''delete from best_score where user_id = :a and song_id = :b and difficulty = :c''', { + 'a': user_id, 'b': i['song_id'], 'c': i['difficulty']}) + c.execute('''insert into best_score values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n)''', { + 'a': user_id, 'b': i['song_id'], 'c': i['difficulty'], 'd': i['score'], 'e': i['shiny_perfect_count'], 'f': i['perfect_count'], 'g': i['near_count'], 'h': i['miss_count'], 'i': i['health'], 'j': i['modifier'], 'k': i['time_played'], 'l': clear_type, 'm': clear_type, 'n': rating}) + + ptt = get_user_ptt(c, user_id) # 更新PTT + c.execute('''update user set rating_ptt = :a where user_id = :b''', { + 'a': ptt, 'b': user_id}) + conn.commit() + conn.close() + return None + + +def arc_all_get(user_id): + # 从云端同步,返回字典 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select * from best_score where user_id = :a''', + {'a': user_id}) + x = c.fetchall() + song_1 = [] + song_2 = [] + song_3 = [] + if x != []: + for i in x: + if i[11] != 0: + song_1.append({ + "grade": get_song_grade(i[3]), + "difficulty": i[2], + "song_id": i[1] + }) + song_2.append({ + "ct": 0, + "clear_type": i[11], + "difficulty": i[2], + "song_id": i[1] + }) + song_3.append({ + "ct": 0, + "time_played": i[10], + "modifier": i[9], + "health": i[8], + "miss_count": i[7], + "near_count": i[6], + "perfect_count": i[5], + "shiny_perfect_count": i[4], + "score": i[3], + "difficulty": i[2], + "version": 1, + "song_id": i[1] + }) + + conn.commit() + conn.close() + return { + "user_id": user_id, + "story": { + "": [{ + "r": True, + "c": True, + "mi": 1, + "ma": 1 + }, { + "r": True, + "c": True, + "mi": 2, + "ma": 1 + }, { + "r": True, + "c": True, + "mi": 3, + "ma": 1 + }, { + "r": True, + "c": True, + "mi": 4, + "ma": 1 + }, { + "r": True, + "c": True, + "mi": 5, + "ma": 1 + }, { + "r": True, + "c": True, + "mi": 6, + "ma": 1 + }, { + "r": True, + "c": True, + "mi": 7, + "ma": 1 + }, { + "r": True, + "c": True, + "mi": 8, + "ma": 1 + }, { + "r": True, + "c": True, + "mi": 9, + "ma": 1 + }, { + "r": True, + "c": True, + "mi": 1, + "ma": 2 + }, { + "r": True, + "c": True, + "mi": 2, + "ma": 2 + }, { + "r": True, + "c": True, + "mi": 3, + "ma": 2 + }, { + "r": True, + "c": True, + "mi": 4, + "ma": 2 + }, { + "r": True, + "c": True, + "mi": 5, + "ma": 2 + }, { + "r": True, + "c": True, + "mi": 6, + "ma": 2 + }, { + "r": True, + "c": True, + "mi": 7, + "ma": 2 + }, { + "r": True, + "c": True, + "mi": 8, + "ma": 2 + }, { + "r": True, + "c": True, + "mi": 9, + "ma": 2 + }, { + "r": True, + "c": True, + "mi": 1, + "ma": 100 + }, { + "r": True, + "c": True, + "mi": 2, + "ma": 100 + }, { + "r": True, + "c": True, + "mi": 3, + "ma": 100 + }, { + "r": True, + "c": True, + "mi": 4, + "ma": 100 + }, { + "r": True, + "c": True, + "mi": 5, + "ma": 100 + }, { + "r": True, + "c": True, + "mi": 1, + "ma": 101 + }, { + "r": True, + "c": True, + "mi": 2, + "ma": 101 + }, { + "r": True, + "c": True, + "mi": 3, + "ma": 101 + }, { + "r": True, + "c": True, + "mi": 4, + "ma": 101 + }, { + "r": True, + "c": True, + "mi": 5, + "ma": 101 + }, { + "r": True, + "c": True, + "mi": 6, + "ma": 101 + }, { + "r": True, + "c": True, + "mi": 7, + "ma": 101 + }, { + "r": True, + "c": True, + "mi": 8, + "ma": 101 + }, { + "r": True, + "c": True, + "mi": 1, + "ma": 3 + }, { + "r": True, + "c": True, + "mi": 2, + "ma": 3 + }, { + "r": True, + "c": True, + "mi": 3, + "ma": 3 + }, { + "r": True, + "c": True, + "mi": 4, + "ma": 3 + }, { + "r": True, + "c": True, + "mi": 5, + "ma": 3 + }, { + "r": True, + "c": True, + "mi": 6, + "ma": 3 + }, { + "r": True, + "c": True, + "mi": 1, + "ma": 4 + }, { + "r": True, + "c": True, + "mi": 2, + "ma": 4 + }, { + "r": True, + "c": True, + "mi": 3, + "ma": 4 + }, { + "r": True, + "c": True, + "mi": 4, + "ma": 4 + }, { + "r": True, + "c": True, + "mi": 5, + "ma": 4 + }, { + "r": True, + "c": True, + "mi": 6, + "ma": 4 + }, { + "r": True, + "c": True, + "mi": 7, + "ma": 4 + }, { + "r": True, + "c": True, + "mi": 8, + "ma": 4 + }, { + "r": True, + "c": True, + "mi": 1, + "ma": 5 + }, { + "r": True, + "c": True, + "mi": 2, + "ma": 5 + }, { + "r": True, + "c": True, + "mi": 3, + "ma": 5 + }, { + "r": True, + "c": True, + "mi": 4, + "ma": 5 + }, { + "r": True, + "c": True, + "mi": 5, + "ma": 5 + }, { + "r": True, + "c": True, + "mi": 6, + "ma": 5 + }, { + "r": True, + "c": True, + "mi": 1, + "ma": 6 + }, { + "r": True, + "c": True, + "mi": 2, + "ma": 6 + }, { + "r": True, + "c": True, + "mi": 3, + "ma": 6 + }] + }, + "devicemodelname": { + "val": "MopeMope" + }, + "installid": { + "val": "b5e064cf-1a3f-4e64-9636-fce4accc9011" + }, + "unlocklist": { + "": [{ + "complete": 1, + "unlock_key": "worldvanquisher|2|0" + }, { + "complete": 1, + "unlock_key": "worldvanquisher|1|0" + }, { + "complete": 1, + "unlock_key": "worldexecuteme|2|0" + }, { + "complete": 1, + "unlock_key": "viciousheroism|2|0" + }, { + "complete": 1, + "unlock_key": "vector|2|0" + }, { + "complete": 1, + "unlock_key": "valhallazero|2|0" + }, { + "complete": 1, + "unlock_key": "tiferet|1|0" + }, { + "complete": 1, + "unlock_key": "tiemedowngently|1|0" + }, { + "complete": 1, + "unlock_key": "tempestissimo|0|101" + }, { + "complete": 1, + "unlock_key": "syro|2|0" + }, { + "complete": 1, + "unlock_key": "suomi|1|0" + }, { + "complete": 1, + "unlock_key": "solitarydream|2|0" + }, { + "complete": 1, + "unlock_key": "snowwhite|2|0" + }, { + "complete": 1, + "unlock_key": "sheriruth|2|0" + }, { + "complete": 1, + "unlock_key": "senkyou|2|0" + }, { + "complete": 1, + "unlock_key": "senkyou|1|0" + }, { + "complete": 1, + "unlock_key": "scarletlance|2|0" + }, { + "complete": 1, + "unlock_key": "scarletlance|1|0" + }, { + "complete": 1, + "unlock_key": "rugie|2|0" + }, { + "complete": 1, + "unlock_key": "rugie|1|0" + }, { + "complete": 1, + "unlock_key": "rise|2|0" + }, { + "complete": 1, + "unlock_key": "revixy|2|0" + }, { + "complete": 1, + "unlock_key": "reinvent|2|0" + }, { + "complete": 1, + "unlock_key": "reinvent|1|0" + }, { + "complete": 1, + "unlock_key": "redandblue|2|0" + }, { + "complete": 1, + "unlock_key": "redandblue|1|0" + }, { + "complete": 1, + "unlock_key": "rabbitintheblackroom|2|0" + }, { + "complete": 1, + "unlock_key": "rabbitintheblackroom|1|0" + }, { + "complete": 1, + "unlock_key": "worldexecuteme|1|0" + }, { + "complete": 1, + "unlock_key": "ringedgenesis|2|0" + }, { + "complete": 1, + "unlock_key": "quon|1|0" + }, { + "complete": 1, + "unlock_key": "qualia|2|0" + }, { + "complete": 1, + "unlock_key": "purgatorium|2|0" + }, { + "complete": 1, + "unlock_key": "supernova|2|0" + }, { + "complete": 1, + "unlock_key": "saikyostronger|2|3|einherjar|2" + }, { + "complete": 1, + "unlock_key": "purgatorium|1|0" + }, { + "complete": 1, + "unlock_key": "pragmatism|2|0" + }, { + "complete": 1, + "unlock_key": "ouroboros|2|0" + }, { + "complete": 1, + "unlock_key": "ouroboros|1|0" + }, { + "complete": 1, + "unlock_key": "oracle|1|0" + }, { + "complete": 1, + "unlock_key": "onelastdrive|2|0" + }, { + "complete": 1, + "unlock_key": "onelastdrive|1|0" + }, { + "complete": 1, + "unlock_key": "oblivia|2|0" + }, { + "complete": 1, + "unlock_key": "memoryforest|1|0" + }, { + "complete": 1, + "unlock_key": "melodyoflove|2|0" + }, { + "complete": 1, + "unlock_key": "saikyostronger|2|3|laqryma|2" + }, { + "complete": 1, + "unlock_key": "melodyoflove|1|0" + }, { + "complete": 1, + "unlock_key": "lucifer|2|0" + }, { + "complete": 1, + "unlock_key": "saikyostronger|2|3|izana|2" + }, { + "complete": 1, + "unlock_key": "halcyon|1|0" + }, { + "complete": 1, + "unlock_key": "memoryforest|2|0" + }, { + "complete": 1, + "unlock_key": "tiemedowngently|2|0" + }, { + "complete": 1, + "unlock_key": "lostdesire|1|0" + }, { + "complete": 1, + "unlock_key": "viciousheroism|1|0" + }, { + "complete": 1, + "unlock_key": "flyburg|1|0" + }, { + "complete": 1, + "unlock_key": "lostcivilization|2|0" + }, { + "complete": 1, + "unlock_key": "infinityheaven|1|0" + }, { + "complete": 1, + "unlock_key": "lostdesire|2|0" + }, { + "complete": 1, + "unlock_key": "ignotus|2|0" + }, { + "complete": 1, + "unlock_key": "harutopia|2|0" + }, { + "complete": 1, + "unlock_key": "revixy|1|0" + }, { + "complete": 1, + "unlock_key": "aterlbus|1|0" + }, { + "complete": 1, + "unlock_key": "linearaccelerator|2|0" + }, { + "complete": 1, + "unlock_key": "guardina|2|0" + }, { + "complete": 1, + "unlock_key": "corpssansorganes|2|0" + }, { + "complete": 1, + "unlock_key": "linearaccelerator|1|0" + }, { + "complete": 1, + "unlock_key": "guardina|1|0" + }, { + "complete": 1, + "unlock_key": "saikyostronger|2|0" + }, { + "complete": 1, + "unlock_key": "guardina|0|0" + }, { + "complete": 1, + "unlock_key": "valhallazero|1|0" + }, { + "complete": 1, + "unlock_key": "grimheart|1|0" + }, { + "complete": 1, + "unlock_key": "blaster|2|0" + }, { + "complete": 1, + "unlock_key": "grievouslady|2|101" + }, { + "complete": 1, + "unlock_key": "partyvinyl|2|0" + }, { + "complete": 1, + "unlock_key": "darakunosono|1|0" + }, { + "complete": 1, + "unlock_key": "grievouslady|1|101" + }, { + "complete": 1, + "unlock_key": "goodtek|1|0" + }, { + "complete": 1, + "unlock_key": "tempestissimo|3|101" + }, { + "complete": 1, + "unlock_key": "chronostasis|2|0" + }, { + "complete": 1, + "unlock_key": "gloryroad|2|0" + }, { + "complete": 1, + "unlock_key": "supernova|1|0" + }, { + "complete": 1, + "unlock_key": "singularity|2|0" + }, { + "complete": 1, + "unlock_key": "gloryroad|0|0" + }, { + "complete": 1, + "unlock_key": "shadesoflight|1|0" + }, { + "complete": 1, + "unlock_key": "kanagawa|2|0" + }, { + "complete": 1, + "unlock_key": "genesis|1|0" + }, { + "complete": 1, + "unlock_key": "fractureray|1|101" + }, { + "complete": 1, + "unlock_key": "freefall|2|0" + }, { + "complete": 1, + "unlock_key": "babaroque|1|0" + }, { + "complete": 1, + "unlock_key": "monochromeprincess|2|0" + }, { + "complete": 1, + "unlock_key": "flyburg|2|0" + }, { + "complete": 1, + "unlock_key": "shadesoflight|2|0" + }, { + "complete": 1, + "unlock_key": "espebranch|2|0" + }, { + "complete": 1, + "unlock_key": "qualia|1|0" + }, { + "complete": 1, + "unlock_key": "etherstrike|2|0" + }, { + "complete": 1, + "unlock_key": "tempestissimo|1|101" + }, { + "complete": 1, + "unlock_key": "conflict|1|0" + }, { + "complete": 1, + "unlock_key": "nhelv|1|0" + }, { + "complete": 1, + "unlock_key": "etherstrike|1|0" + }, { + "complete": 1, + "unlock_key": "syro|1|0" + }, { + "complete": 1, + "unlock_key": "anokumene|2|0" + }, { + "complete": 1, + "unlock_key": "essenceoftwilight|2|0" + }, { + "complete": 1, + "unlock_key": "snowwhite|1|0" + }, { + "complete": 1, + "unlock_key": "partyvinyl|1|0" + }, { + "complete": 1, + "unlock_key": "axiumcrisis|1|0" + }, { + "complete": 1, + "unlock_key": "ifi|2|0" + }, { + "complete": 1, + "unlock_key": "espebranch|1|0" + }, { + "complete": 1, + "unlock_key": "lostcivilization|1|0" + }, { + "complete": 1, + "unlock_key": "goodtek|2|0" + }, { + "complete": 1, + "unlock_key": "dandelion|2|0" + }, { + "complete": 1, + "unlock_key": "suomi|2|0" + }, { + "complete": 1, + "unlock_key": "dandelion|1|0" + }, { + "complete": 1, + "unlock_key": "oblivia|1|0" + }, { + "complete": 1, + "unlock_key": "cyberneciacatharsis|1|0" + }, { + "complete": 1, + "unlock_key": "quon|2|0" + }, { + "complete": 1, + "unlock_key": "bookmaker|2|0" + }, { + "complete": 1, + "unlock_key": "chronostasis|1|0" + }, { + "complete": 1, + "unlock_key": "heavensdoor|1|0" + }, { + "complete": 1, + "unlock_key": "tempestissimo|2|101" + }, { + "complete": 1, + "unlock_key": "cyaegha|2|0" + }, { + "complete": 1, + "unlock_key": "axiumcrisis|2|0" + }, { + "complete": 1, + "unlock_key": "blrink|2|0" + }, { + "complete": 1, + "unlock_key": "rise|1|0" + }, { + "complete": 1, + "unlock_key": "cyanine|1|0" + }, { + "complete": 1, + "unlock_key": "ifi|1|0" + }, { + "complete": 1, + "unlock_key": "aterlbus|2|0" + }, { + "complete": 1, + "unlock_key": "dreaminattraction|2|0" + }, { + "complete": 1, + "unlock_key": "bookmaker|1|0" + }, { + "complete": 1, + "unlock_key": "lucifer|1|0" + }, { + "complete": 1, + "unlock_key": "solitarydream|1|0" + }, { + "complete": 1, + "unlock_key": "ringedgenesis|1|0" + }, { + "complete": 1, + "unlock_key": "corpssansorganes|1|0" + }, { + "complete": 1, + "unlock_key": "vector|1|0" + }, { + "complete": 1, + "unlock_key": "infinityheaven|2|0" + }, { + "complete": 1, + "unlock_key": "essenceoftwilight|1|0" + }, { + "complete": 1, + "unlock_key": "conflict|2|0" + }, { + "complete": 1, + "unlock_key": "singularity|1|0" + }, { + "complete": 1, + "unlock_key": "harutopia|1|0" + }, { + "complete": 1, + "unlock_key": "cyberneciacatharsis|2|0" + }, { + "complete": 1, + "unlock_key": "oracle|2|0" + }, { + "complete": 1, + "unlock_key": "clotho|2|0" + }, { + "complete": 1, + "unlock_key": "corpssansorganes|0|0" + }, { + "complete": 1, + "unlock_key": "ignotus|1|0" + }, { + "complete": 1, + "unlock_key": "monochromeprincess|1|0" + }, { + "complete": 1, + "unlock_key": "nirvluce|1|0" + }, { + "complete": 1, + "unlock_key": "lethaeus|1|0" + }, { + "complete": 1, + "unlock_key": "clotho|1|0" + }, { + "complete": 1, + "unlock_key": "blaster|1|0" + }, { + "complete": 1, + "unlock_key": "fractureray|0|101" + }, { + "complete": 1, + "unlock_key": "kanagawa|1|0" + }, { + "complete": 1, + "unlock_key": "darakunosono|2|0" + }, { + "complete": 1, + "unlock_key": "freefall|1|0" + }, { + "complete": 1, + "unlock_key": "nirvluce|2|0" + }, { + "complete": 1, + "unlock_key": "cyanine|2|0" + }, { + "complete": 1, + "unlock_key": "heavensdoor|2|0" + }, { + "complete": 1, + "unlock_key": "genesis|2|0" + }, { + "complete": 1, + "unlock_key": "pragmatism|1|0" + }, { + "complete": 1, + "unlock_key": "nhelv|2|0" + }, { + "complete": 1, + "unlock_key": "halcyon|2|0" + }, { + "complete": 1, + "unlock_key": "blrink|1|0" + }, { + "complete": 1, + "unlock_key": "fractureray|2|101" + }, { + "complete": 1, + "unlock_key": "lethaeus|2|0" + }, { + "complete": 1, + "unlock_key": "sheriruth|1|0" + }, { + "complete": 1, + "unlock_key": "babaroque|2|0" + }, { + "complete": 1, + "unlock_key": "tiferet|2|0" + }, { + "complete": 1, + "unlock_key": "grimheart|2|0" + }, { + "complete": 1, + "unlock_key": "cyaegha|1|0" + }, { + "complete": 1, + "unlock_key": "aiueoon|2|0" + }, { + "complete": 1, + "unlock_key": "gloryroad|1|0" + }, { + "complete": 1, + "unlock_key": "anokumene|1|0" + }, { + "complete": 1, + "unlock_key": "grievouslady|0|101" + }, { + "complete": 1, + "unlock_key": "dreaminattraction|1|0" + }] + }, "clearedsongs": { + "": song_1 + }, + "clearlamps": { + "": song_2 + }, + "scores": { + "": song_3 + }, + "version": { + "val": 1 + } + } diff --git a/v1.3/server/arcworld.py b/latest version/server/arcworld.py similarity index 96% rename from v1.3/server/arcworld.py rename to latest version/server/arcworld.py index e4efa9b..ca8e8c0 100644 --- a/v1.3/server/arcworld.py +++ b/latest version/server/arcworld.py @@ -1,259 +1,259 @@ -import json -import sqlite3 -import os - - -def int2b(x): - # int与布尔值转换 - if x is None or x == 0: - return False - else: - return True - - -def get_world_name(file_dir='./database/map'): - # 获取所有地图名称,返回列表 - L = [] - for root, dirs, files in os.walk(file_dir): - for file in files: - if os.path.splitext(file)[1] == '.json': - L.append(os.path.splitext(file)[0]) - return L - - -def get_world_info(map_id): - # 读取json文件内容,返回字典 - f = open('./database/map/'+map_id+'.json', 'r') - world_info = json.load(f) - f.close() - return world_info - - -def get_user_world_info(user_id, map_id): - # 读取json文件内容,加上用户信息,返回字典 - info = get_world_info(map_id) - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - c.execute('''select * from user_world where map_id = :a and user_id = :b''', - {'a': map_id, 'b': user_id}) - x = c.fetchone() - if x: - info['curr_position'] = x[2] - info['curr_capture'] = x[3] - info['is_locked'] = int2b(x[4]) - else: - c.execute('''insert into user_world values(:a,:b,0,0,0)''', { - 'a': user_id, 'b': map_id}) - conn.commit() - conn.close() - return info - - -def get_current_map(user_id): - # 得到user的当前图,返回字符串 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - c.execute('''select current_map from user where user_id = :a''', - {'a': user_id}) - x = c.fetchone() - re = '' - if x: - re = x[0] - - conn.commit() - conn.close() - return re - - -def get_world_all(user_id): - # 读取所有地图信息并处理,返回字典列表 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - worlds = get_world_name() - re = [] - for map_id in worlds: - info = get_world_info(map_id) - steps = info['steps'] - del info['steps'] - rewards = [] - for step in steps: - if 'items' in step: - rewards.append( - {'items': step['items'], 'position': step['position']}) - info['rewards'] = rewards - c.execute('''select * from user_world where map_id = :a and user_id = :b''', - {'a': map_id, 'b': user_id}) - x = c.fetchone() - if x: - info['curr_position'] = x[2] - info['curr_capture'] = x[3] - info['is_locked'] = int2b(x[4]) - else: - c.execute('''insert into user_world values(:a,:b,0,0,0)''', { - 'a': user_id, 'b': map_id}) - - re.append(info) - - conn.commit() - conn.close() - return re - - -def get_user_world(user_id, map_id): - # 获取用户图信息,返回字典 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - c.execute('''select * from user_world where map_id = :a and user_id = :b''', - {'a': map_id, 'b': user_id}) - x = c.fetchone() - re = { - "user_id": user_id, - "curr_position": 0, - "curr_capture": 0, - "is_locked": False, - "map_id": map_id - } - if x: - re['curr_position'] = x[2] - re['curr_capture'] = x[3] - re['is_locked'] = int2b(x[4]) - else: - c.execute('''insert into user_world values(:a,:b,0,0,0)''', { - 'a': user_id, 'b': map_id}) - - conn.commit() - conn.close() - return re - - -def change_user_current_map(user_id, map_id): - # 改变用户当前图 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - c.execute('''update user set current_map = :a where user_id=:b''', { - 'a': map_id, 'b': user_id}) - conn.commit() - conn.close() - return None - - -def play_world_song(user_id, args): - # 声明是世界模式的打歌,并且记录加成信息 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - - stamina_multiply = 1 - fragment_multiply = 100 - prog_boost_multiply = 0 - if 'stamina_multiply' in args: - stamina_multiply = int(args['stamina_multiply']) - if 'fragment_multiply' in args: - fragment_multiply = int(args['fragment_multiply']) - if 'prog_boost_multiply' in args: - prog_boost_multiply = int(args['prog_boost_multiply']) - - c.execute('''delete from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', { - 'a': user_id, 'b': args['song_id'], 'c': args['difficulty']}) - c.execute('''insert into world_songplay values(:a,:b,:c,:d,:e,:f)''', { - 'a': user_id, 'b': args['song_id'], 'c': args['difficulty'], 'd': stamina_multiply, 'e': fragment_multiply, 'f': prog_boost_multiply}) - - conn.commit() - conn.close() - return None - - -def climb_step(user_id, map_id, step, prev_capture, prev_position): - # 爬梯子,返回奖励列表,台阶列表,当前的位置和坐标,图信息 - info = get_world_info(map_id) - step_count = int(info['step_count']) - - restrict_ids = [[]] * step_count - capture = [0] * step_count - reward_bundle = [""] * step_count # 暂且不用 - restrict_id = [""] * step_count - restrict_type = [""] * step_count - items = [[]] * step_count - step_type = [[]] * step_count - speed_limit_value = [0] * step_count - plus_stamina_value = [0] * step_count - - for i in info['steps']: - capture[i['position']] = i['capture'] - if 'items' in i: - items[i['position']] = i['items'] - if 'restrict_id' in i: - restrict_id[i['position']] = i['restrict_id'] - if 'restrict_ids' in i: - restrict_ids[i['position']] = i['restrict_ids'] - if 'restrict_type' in i: - restrict_type[i['position']] = i['restrict_type'] - if 'step_type' in i: - step_type[i['position']] = i['step_type'] - if "speedlimit" in i['step_type']: - speed_limit_value[i['position']] = i['speed_limit_value'] - if "plusstamina" in i['step_type']: - plus_stamina_value[i['position']] = i['plus_stamina_value'] - - if info['is_beyond']: # beyond判断 - dt = info['beyond_health'] - prev_capture - if dt >= step: - curr_capture = prev_capture + step - else: - curr_capture = info['beyond_health'] - i = 0 - t = prev_capture + step - while i < step_count and t > 0: - dt = capture[i] - if dt > t: - t = 0 - else: - t -= dt - i += 1 - if i >= step_count: - curr_position = step_count - 1 - else: - curr_position = i - - else: - i = prev_position - j = prev_capture - t = step - while t > 0 and i < step_count: - dt = capture[i] - j - if dt > t: - j += t - t = 0 - else: - t -= dt - j = 0 - i += 1 - if i >= step_count: - curr_position = step_count - 1 - curr_capture = 0 - else: - curr_position = i - curr_capture = j - - rewards = [] - steps = [] - for i in range(prev_position, curr_position+1): - if items[i]: - rewards.append({'position': i, 'items': items[i]}) - x = { - "map_id": map_id, - "position": i, - "restrict_ids": restrict_ids[i], - "capture": capture[i], - "reward_bundle": reward_bundle[i], - "restrict_id": restrict_id[i], - "restrict_type": restrict_type[i] - } - if step_type[i]: - x['step_type'] = step_type[i] - if speed_limit_value[i]: - x['speed_limit_value'] = speed_limit_value[i] - if plus_stamina_value[i]: - x['plus_stamina_value'] = plus_stamina_value[i] - steps.append(x) - - return rewards, steps, curr_position, curr_capture, info +import json +import sqlite3 +import os + + +def int2b(x): + # int与布尔值转换 + if x is None or x == 0: + return False + else: + return True + + +def get_world_name(file_dir='./database/map'): + # 获取所有地图名称,返回列表 + L = [] + for root, dirs, files in os.walk(file_dir): + for file in files: + if os.path.splitext(file)[1] == '.json': + L.append(os.path.splitext(file)[0]) + return L + + +def get_world_info(map_id): + # 读取json文件内容,返回字典 + f = open('./database/map/'+map_id+'.json', 'r') + world_info = json.load(f) + f.close() + return world_info + + +def get_user_world_info(user_id, map_id): + # 读取json文件内容,加上用户信息,返回字典 + info = get_world_info(map_id) + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select * from user_world where map_id = :a and user_id = :b''', + {'a': map_id, 'b': user_id}) + x = c.fetchone() + if x: + info['curr_position'] = x[2] + info['curr_capture'] = x[3] + info['is_locked'] = int2b(x[4]) + else: + c.execute('''insert into user_world values(:a,:b,0,0,0)''', { + 'a': user_id, 'b': map_id}) + conn.commit() + conn.close() + return info + + +def get_current_map(user_id): + # 得到user的当前图,返回字符串 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select current_map from user where user_id = :a''', + {'a': user_id}) + x = c.fetchone() + re = '' + if x: + re = x[0] + + conn.commit() + conn.close() + return re + + +def get_world_all(user_id): + # 读取所有地图信息并处理,返回字典列表 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + worlds = get_world_name() + re = [] + for map_id in worlds: + info = get_world_info(map_id) + steps = info['steps'] + del info['steps'] + rewards = [] + for step in steps: + if 'items' in step: + rewards.append( + {'items': step['items'], 'position': step['position']}) + info['rewards'] = rewards + c.execute('''select * from user_world where map_id = :a and user_id = :b''', + {'a': map_id, 'b': user_id}) + x = c.fetchone() + if x: + info['curr_position'] = x[2] + info['curr_capture'] = x[3] + info['is_locked'] = int2b(x[4]) + else: + c.execute('''insert into user_world values(:a,:b,0,0,0)''', { + 'a': user_id, 'b': map_id}) + + re.append(info) + + conn.commit() + conn.close() + return re + + +def get_user_world(user_id, map_id): + # 获取用户图信息,返回字典 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select * from user_world where map_id = :a and user_id = :b''', + {'a': map_id, 'b': user_id}) + x = c.fetchone() + re = { + "user_id": user_id, + "curr_position": 0, + "curr_capture": 0, + "is_locked": False, + "map_id": map_id + } + if x: + re['curr_position'] = x[2] + re['curr_capture'] = x[3] + re['is_locked'] = int2b(x[4]) + else: + c.execute('''insert into user_world values(:a,:b,0,0,0)''', { + 'a': user_id, 'b': map_id}) + + conn.commit() + conn.close() + return re + + +def change_user_current_map(user_id, map_id): + # 改变用户当前图 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''update user set current_map = :a where user_id=:b''', { + 'a': map_id, 'b': user_id}) + conn.commit() + conn.close() + return None + + +def play_world_song(user_id, args): + # 声明是世界模式的打歌,并且记录加成信息 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + + stamina_multiply = 1 + fragment_multiply = 100 + prog_boost_multiply = 0 + if 'stamina_multiply' in args: + stamina_multiply = int(args['stamina_multiply']) + if 'fragment_multiply' in args: + fragment_multiply = int(args['fragment_multiply']) + if 'prog_boost_multiply' in args: + prog_boost_multiply = int(args['prog_boost_multiply']) + + c.execute('''delete from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', { + 'a': user_id, 'b': args['song_id'], 'c': args['difficulty']}) + c.execute('''insert into world_songplay values(:a,:b,:c,:d,:e,:f)''', { + 'a': user_id, 'b': args['song_id'], 'c': args['difficulty'], 'd': stamina_multiply, 'e': fragment_multiply, 'f': prog_boost_multiply}) + + conn.commit() + conn.close() + return None + + +def climb_step(user_id, map_id, step, prev_capture, prev_position): + # 爬梯子,返回奖励列表,台阶列表,当前的位置和坐标,图信息 + info = get_world_info(map_id) + step_count = int(info['step_count']) + + restrict_ids = [[]] * step_count + capture = [0] * step_count + reward_bundle = [""] * step_count # 暂且不用 + restrict_id = [""] * step_count + restrict_type = [""] * step_count + items = [[]] * step_count + step_type = [[]] * step_count + speed_limit_value = [0] * step_count + plus_stamina_value = [0] * step_count + + for i in info['steps']: + capture[i['position']] = i['capture'] + if 'items' in i: + items[i['position']] = i['items'] + if 'restrict_id' in i: + restrict_id[i['position']] = i['restrict_id'] + if 'restrict_ids' in i: + restrict_ids[i['position']] = i['restrict_ids'] + if 'restrict_type' in i: + restrict_type[i['position']] = i['restrict_type'] + if 'step_type' in i: + step_type[i['position']] = i['step_type'] + if "speedlimit" in i['step_type']: + speed_limit_value[i['position']] = i['speed_limit_value'] + if "plusstamina" in i['step_type']: + plus_stamina_value[i['position']] = i['plus_stamina_value'] + + if info['is_beyond']: # beyond判断 + dt = info['beyond_health'] - prev_capture + if dt >= step: + curr_capture = prev_capture + step + else: + curr_capture = info['beyond_health'] + i = 0 + t = prev_capture + step + while i < step_count and t > 0: + dt = capture[i] + if dt > t: + t = 0 + else: + t -= dt + i += 1 + if i >= step_count: + curr_position = step_count - 1 + else: + curr_position = i + + else: + i = prev_position + j = prev_capture + t = step + while t > 0 and i < step_count: + dt = capture[i] - j + if dt > t: + j += t + t = 0 + else: + t -= dt + j = 0 + i += 1 + if i >= step_count: + curr_position = step_count - 1 + curr_capture = 0 + else: + curr_position = i + curr_capture = j + + rewards = [] + steps = [] + for i in range(prev_position, curr_position+1): + if items[i]: + rewards.append({'position': i, 'items': items[i]}) + x = { + "map_id": map_id, + "position": i, + "restrict_ids": restrict_ids[i], + "capture": capture[i], + "reward_bundle": reward_bundle[i], + "restrict_id": restrict_id[i], + "restrict_type": restrict_type[i] + } + if step_type[i]: + x['step_type'] = step_type[i] + if speed_limit_value[i]: + x['speed_limit_value'] = speed_limit_value[i] + if plus_stamina_value[i]: + x['plus_stamina_value'] = plus_stamina_value[i] + steps.append(x) + + return rewards, steps, curr_position, curr_capture, info diff --git a/v1.3/server/auth.py b/latest version/server/auth.py similarity index 97% rename from v1.3/server/auth.py rename to latest version/server/auth.py index be3b3df..5a8b6d3 100644 --- a/v1.3/server/auth.py +++ b/latest version/server/auth.py @@ -1,150 +1,150 @@ -import sqlite3 -import hashlib -import time -import server.arcworld - - -def arc_login(name: str, password: str) -> str: # 登录判断 - # 查询数据库中的user表,验证账号密码,返回并记录token - # token采用user_id和时间戳连接后hash生成(真的是瞎想的,没用bear) - # 密码和token的加密方式为 SHA-256 - - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest() - c.execute('''select user_id from user where name = :name and password = :password''', { - 'name': name, 'password': hash_pwd}) - x = c.fetchone() - if x is not None: - user_id = str(x[0]) - now = int(time.time() * 1000) - token = hashlib.sha256((user_id + str(now)).encode("utf8")).hexdigest() - c.execute( - '''select exists(select * from login where user_id = :user_id)''', {"user_id": user_id}) - - if c.fetchone() == (1,): # 删掉多余token - c.execute('''delete from login where user_id = :user_id''', - {'user_id': user_id}) - - c.execute('''insert into login(access_token, user_id) values(:access_token, :user_id)''', { - 'user_id': user_id, 'access_token': token}) - conn.commit() - conn.close() - return token - - conn.commit() - conn.close() - return None - - -def arc_register(name: str, password: str): # 注册 - # 账号注册,只记录hash密码和用户名,生成user_id和user_code,自动登录返回token - # token和密码的处理同登录部分 - - def build_user_code(c): - # 生成9位的user_code,用的自然是随机 - import random - flag = True - while flag: - user_code = ''.join([str(random.randint(0, 9)) for i in range(9)]) - c.execute('''select exists(select * from user where user_code = :user_code)''', - {'user_code': user_code}) - if c.fetchone() == (0,): - flag = False - return user_code - - def build_user_id(c): - # 生成user_id,往后加1 - c.execute('''select max(user_id) from user''') - x = c.fetchone() - if x[0] is not None: - return x[0] + 1 - else: - return 2000001 - - # def insert_user_char(c, user_id): - # # 为用户添加所有可用角色 - # for i in range(0, 38): - # if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21]: - # sql = 'insert into user_char values('+str(user_id)+','+str( - # i)+''',30,25000,25000,90,90,90,'',0,0,'',0,1,1)''' - # c.execute(sql) - # else: - # if i != 5: - # sql = 'insert into user_char values('+str(user_id)+','+str( - # i)+''',30,25000,25000,90,90,90,'',0,0,'',0,0,0)''' - # c.execute(sql) - def insert_user_char(c, user_id): - # 为用户添加所有可用角色 - c.execute('''select * from character''') - x = c.fetchall() - if x != []: - for i in x: - c.execute('''insert into user_char values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o)''', { - 'a': user_id, 'b': i[0], 'c': i[2], 'd': i[3], 'e': i[4], 'f': i[5], 'g': i[6], 'h': i[7], 'i': i[8], 'j': i[9], 'k': i[10], 'l': i[11], 'm': i[12], 'n': i[14], 'o': i[15]}) - - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest() - c.execute( - '''select exists(select * from user where name = :name)''', {'name': name}) - if c.fetchone() == (0,): - user_code = build_user_code(c) - user_id = build_user_id(c) - now = int(time.time() * 1000) - c.execute('''insert into user(user_id, name, password, join_date, user_code, rating_ptt, - character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map) - values(:user_id, :name, :password, :join_date, :user_code, 0, 0, 0, 0, 0, 0, -1, 0, '') - ''', {'user_code': user_code, 'user_id': user_id, 'join_date': now, 'name': name, 'password': hash_pwd}) - c.execute('''insert into recent30(user_id) values(:user_id)''', { - 'user_id': user_id}) - - token = hashlib.sha256( - (str(user_id) + str(now)).encode("utf8")).hexdigest() - c.execute('''insert into login(access_token, user_id) values(:access_token, :user_id)''', { - 'user_id': user_id, 'access_token': token}) - - insert_user_char(c, user_id) - conn.commit() - conn.close() - return user_id, token, 0 - else: - conn.commit() - conn.close() - return None, None, 101 - - -def token_get_id(token: str): - # 用token获取id,没有考虑不同用户token相同情况,说不定会有bug - - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - c.execute('''select user_id from login where access_token = :token''', { - 'token': token}) - x = c.fetchone() - if x is not None: - conn.commit() - conn.close() - return x[0] - else: - conn.commit() - conn.close() - return None - - -def code_get_id(user_code): - # 用user_code获取id - - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - c.execute('''select user_id from user where user_code = :a''', - {'a': user_code}) - x = c.fetchone() - if x is not None: - conn.commit() - conn.close() - return x[0] - else: - conn.commit() - conn.close() - return None +import sqlite3 +import hashlib +import time +import server.arcworld + + +def arc_login(name: str, password: str) -> str: # 登录判断 + # 查询数据库中的user表,验证账号密码,返回并记录token + # token采用user_id和时间戳连接后hash生成(真的是瞎想的,没用bear) + # 密码和token的加密方式为 SHA-256 + + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest() + c.execute('''select user_id from user where name = :name and password = :password''', { + 'name': name, 'password': hash_pwd}) + x = c.fetchone() + if x is not None: + user_id = str(x[0]) + now = int(time.time() * 1000) + token = hashlib.sha256((user_id + str(now)).encode("utf8")).hexdigest() + c.execute( + '''select exists(select * from login where user_id = :user_id)''', {"user_id": user_id}) + + if c.fetchone() == (1,): # 删掉多余token + c.execute('''delete from login where user_id = :user_id''', + {'user_id': user_id}) + + c.execute('''insert into login(access_token, user_id) values(:access_token, :user_id)''', { + 'user_id': user_id, 'access_token': token}) + conn.commit() + conn.close() + return token + + conn.commit() + conn.close() + return None + + +def arc_register(name: str, password: str): # 注册 + # 账号注册,只记录hash密码和用户名,生成user_id和user_code,自动登录返回token + # token和密码的处理同登录部分 + + def build_user_code(c): + # 生成9位的user_code,用的自然是随机 + import random + flag = True + while flag: + user_code = ''.join([str(random.randint(0, 9)) for i in range(9)]) + c.execute('''select exists(select * from user where user_code = :user_code)''', + {'user_code': user_code}) + if c.fetchone() == (0,): + flag = False + return user_code + + def build_user_id(c): + # 生成user_id,往后加1 + c.execute('''select max(user_id) from user''') + x = c.fetchone() + if x[0] is not None: + return x[0] + 1 + else: + return 2000001 + + # def insert_user_char(c, user_id): + # # 为用户添加所有可用角色 + # for i in range(0, 38): + # if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21]: + # sql = 'insert into user_char values('+str(user_id)+','+str( + # i)+''',30,25000,25000,90,90,90,'',0,0,'',0,1,1)''' + # c.execute(sql) + # else: + # if i != 5: + # sql = 'insert into user_char values('+str(user_id)+','+str( + # i)+''',30,25000,25000,90,90,90,'',0,0,'',0,0,0)''' + # c.execute(sql) + def insert_user_char(c, user_id): + # 为用户添加所有可用角色 + c.execute('''select * from character''') + x = c.fetchall() + if x != []: + for i in x: + c.execute('''insert into user_char values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o)''', { + 'a': user_id, 'b': i[0], 'c': i[2], 'd': i[3], 'e': i[4], 'f': i[5], 'g': i[6], 'h': i[7], 'i': i[8], 'j': i[9], 'k': i[10], 'l': i[11], 'm': i[12], 'n': i[14], 'o': i[15]}) + + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest() + c.execute( + '''select exists(select * from user where name = :name)''', {'name': name}) + if c.fetchone() == (0,): + user_code = build_user_code(c) + user_id = build_user_id(c) + now = int(time.time() * 1000) + c.execute('''insert into user(user_id, name, password, join_date, user_code, rating_ptt, + character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map) + values(:user_id, :name, :password, :join_date, :user_code, 0, 0, 0, 0, 0, 0, -1, 0, '') + ''', {'user_code': user_code, 'user_id': user_id, 'join_date': now, 'name': name, 'password': hash_pwd}) + c.execute('''insert into recent30(user_id) values(:user_id)''', { + 'user_id': user_id}) + + token = hashlib.sha256( + (str(user_id) + str(now)).encode("utf8")).hexdigest() + c.execute('''insert into login(access_token, user_id) values(:access_token, :user_id)''', { + 'user_id': user_id, 'access_token': token}) + + insert_user_char(c, user_id) + conn.commit() + conn.close() + return user_id, token, 0 + else: + conn.commit() + conn.close() + return None, None, 101 + + +def token_get_id(token: str): + # 用token获取id,没有考虑不同用户token相同情况,说不定会有bug + + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select user_id from login where access_token = :token''', { + 'token': token}) + x = c.fetchone() + if x is not None: + conn.commit() + conn.close() + return x[0] + else: + conn.commit() + conn.close() + return None + + +def code_get_id(user_code): + # 用user_code获取id + + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select user_id from user where user_code = :a''', + {'a': user_code}) + x = c.fetchone() + if x is not None: + conn.commit() + conn.close() + return x[0] + else: + conn.commit() + conn.close() + return None diff --git a/v1.3/server/info.py b/latest version/server/info.py similarity index 96% rename from v1.3/server/info.py rename to latest version/server/info.py index 2a75089..01bb12c 100644 --- a/v1.3/server/info.py +++ b/latest version/server/info.py @@ -1,491 +1,491 @@ -import sqlite3 -import server.arcworld - - -def int2b(x): - # int与布尔值转换 - if x is None or x == 0: - return False - else: - return True - - -def get_recent_score(c, user_id): - # 得到用户最近一次的成绩,返回列表 - c.execute('''select * from user where user_id = :x''', {'x': user_id}) - x = c.fetchone() - if x is not None: - if x[11] is not None: - c.execute('''select best_clear_type from best_score where user_id=:u and song_id=:s and difficulty=:d''', { - 'u': user_id, 's': x[11], 'd': x[12]}) - y = c.fetchone() - if y is not None: - best_clear_type = y[0] - else: - best_clear_type = x[21] - - return [{ - "rating": x[22], - "modifier": x[19], - "time_played": x[20], - "health": x[18], - "best_clear_type": best_clear_type, - "clear_type": x[21], - "miss_count": x[17], - "near_count": x[16], - "perfect_count": x[15], - "shiny_perfect_count": x[14], - "score": x[13], - "difficulty": x[12], - "song_id": x[11] - }] - return [] - - -def get_user_character(c, user_id): - # 得到用户拥有的角色列表,返回列表 - c.execute('''select * from user_char where user_id = :user_id''', - {'user_id': user_id}) - x = c.fetchall() - if x != []: - s = [] - for i in x: - char_name = '' - c.execute( - '''select name from character where character_id = :x''', {'x': i[1]}) - y = c.fetchone() - if y is not None: - char_name = y[0] - s.append({ - "is_uncapped_override": int2b(i[14]), - "is_uncapped": int2b(i[13]), - "uncap_cores": [], - "char_type": i[12], - "skill_id_uncap": i[11], - "skill_requires_uncap": int2b(i[10]), - "skill_unlock_level": i[9], - "skill_id": i[8], - "overdrive": i[7], - "prog": i[6], - "frag": i[5], - "level_exp": i[4], - "exp": i[3], - "level": i[2], - "name": char_name, - "character_id": i[1] - }) - - return s - else: - return [] - - -def get_user_friend(c, user_id): - # 得到用户的朋友列表,返回列表 - c.execute('''select user_id_other from friend where user_id_me = :user_id''', { - 'user_id': user_id}) - x = c.fetchall() - s = [] - if x != [] and x[0][0] is not None: - - for i in x: - c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''', - {'x': i[0], 'y': user_id}) - if c.fetchone() == (1,): - is_mutual = True - else: - is_mutual = False - - c.execute('''select * from user where user_id = :x''', {'x': i[0]}) - y = c.fetchone() - if y is not None: - s.append({ - "is_mutual": is_mutual, - "is_char_uncapped_override": int2b(y[9]), - "is_char_uncapped": int2b(y[8]), - "is_skill_sealed": int2b(y[7]), - "rating": y[5], - "join_date": int(y[3]), - "character": y[6], - "recent_score": get_recent_score(c, i[0]), - "name": y[1], - "user_id": i[0] - }) - - return s - - -def get_value_0(c, user_id): - # 构造value id=0的数据,返回字典 - c.execute('''select * from user where user_id = :x''', {'x': user_id}) - x = c.fetchone() - r = {} - if x is not None: - user_character = get_user_character(c, user_id) - characters = [] - for i in user_character: - characters.append(i['character_id']) - - r = {"is_aprilfools": False, - "curr_available_maps": [], - "character_stats": user_character, - "friends": get_user_friend(c, user_id), - "settings": { - "favorite_character": x[23], - "is_hide_rating": int2b(x[10]), - "max_stamina_notification_enabled": int2b(x[24]) - }, - "user_id": user_id, - "name": x[1], - "user_code": x[4], - "display_name": x[1], - "ticket": 114514, - "character": x[6], - "is_locked_name_duplicate": False, - "is_skill_sealed": int2b(x[7]), - "current_map": x[25], - "prog_boost": 0, - "next_fragstam_ts": -1, - "max_stamina_ts": 1586274871917, - "stamina": 12, - "world_unlocks": [], - "world_songs": ["babaroque", "shadesoflight", "kanagawa", "lucifer", "anokumene", "ignotus", "rabbitintheblackroom", "qualia", "redandblue", "bookmaker", "darakunosono", "espebranch", "blacklotus", "givemeanightmare", "vividtheory", "onefr", "gekka", "vexaria3", "infinityheaven3", "fairytale3", "goodtek3", "suomi", "rugie", "faintlight", "harutopia", "goodtek", "dreaminattraction", "syro", "diode", "freefall", "grimheart", "blaster", "cyberneciacatharsis", "monochromeprincess", "revixy", "vector", "supernova", "nhelv", "purgatorium3", "dement3", "crossover", "guardina", "axiumcrisis", "worldvanquisher", "sheriruth", "pragmatism", "gloryroad", "etherstrike", "corpssansorganes", "lostdesire", "blrink", "essenceoftwilight"], - "singles": ["dataerror", "yourvoiceso", "crosssoul", "impurebird", "auxesia", "modelista", "yozakurafubuki", "surrender", "metallicpunisher", "carminescythe", "bethere", "callmyname", "fallensquare", "dropdead", "alexandrite", "astraltale", "phantasia", "empireofwinter", "libertas", "dottodot", "dreadnought", "mirzam", "heavenlycaress", "filament", "avantraze", "battlenoone", "saikyostronger", "izana", "einherjar", "laqryma", "amygdata", "altale", "feelssoright", "scarletcage", "teriqma", "mahoroba", "badtek", "maliciousmischance", "buchigireberserker", "galaxyfriends", "buchigireberserker2"], - "packs": ["vs", "extend", "dynamix", "prelude", "core", "yugamu", "omatsuri", "zettai", "mirai", "shiawase", "chunithm", "nijuusei", "groovecoaster", "rei", "tonesphere", "lanota"], - "characters": characters, - "cores": [], - "recent_score": get_recent_score(c, user_id), - "max_friend": 50, - "rating": x[5], - "join_date": int(x[3]) - } - - return r - - -def arc_aggregate_small(user_id): - # 返回用户数据 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - r = {"success": True, - "value": [{ - "id": 0, - "value": get_value_0(c, user_id) - }]} - - conn.commit() - conn.close() - return r - - -def arc_aggregate_big(user_id): - # 返回用户数据和地图歌曲信息 - # 因为没有整理地图和曲包数据(不需要世界模式),所以直接复制了 - - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - r = {"success": True, - "value": [{ - "id": 0, - "value": get_value_0(c, user_id) - }, { - "id": 1, - "value": [{ - "name": "core", - "items": [{ - "id": "core", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "shiawase", - "items": [{ - "id": "shiawase", - "type": "pack", - "is_available": True - }, { - "id": "kou", - "type": "character", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1552089600000, - "discount_to": 1552694399000 - }, { - "name": "dynamix", - "items": [{ - "id": "dynamix", - "type": "pack", - "is_available": True - }, { - "id": "sapphire", - "type": "character", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "mirai", - "items": [{ - "id": "mirai", - "type": "pack", - "is_available": True - }, { - "id": "lethe", - "type": "character", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1552089600000, - "discount_to": 1552694399000 - }, { - "name": "yugamu", - "items": [{ - "id": "yugamu", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "lanota", - "items": [{ - "id": "lanota", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "nijuusei", - "items": [{ - "id": "nijuusei", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "rei", - "items": [{ - "id": "rei", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "tonesphere", - "items": [{ - "id": "tonesphere", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "groovecoaster", - "items": [{ - "id": "groovecoaster", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "zettai", - "items": [{ - "id": "zettai", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "chunithm", - "items": [{ - "id": "chunithm", - "type": "pack", - "is_available": True - }], - "price": 300, - "orig_price": 300 - }, { - "name": "prelude", - "items": [{ - "id": "prelude", - "type": "pack", - "is_available": True - }], - "price": 400, - "orig_price": 400 - }, { - "name": "omatsuri", - "items": [{ - "id": "omatsuri", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500 - }, { - "name": "vs", - "items": [{ - "id": "vs", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500 - }, { - "name": "extend", - "items": [{ - "id": "extend", - "type": "pack", - "is_available": True - }], - "price": 700, - "orig_price": 700 - }] - }, { - "id": 2, - "value": {} - }, { - "id": 3, - "value": { - "max_stamina": 12, - "stamina_recover_tick": 1800000, - "core_exp": 250, - "curr_ts": 1599547606825, - "level_steps": [{ - "level": 1, - "level_exp": 0 - }, { - "level": 2, - "level_exp": 50 - }, { - "level": 3, - "level_exp": 100 - }, { - "level": 4, - "level_exp": 150 - }, { - "level": 5, - "level_exp": 200 - }, { - "level": 6, - "level_exp": 300 - }, { - "level": 7, - "level_exp": 450 - }, { - "level": 8, - "level_exp": 650 - }, { - "level": 9, - "level_exp": 900 - }, { - "level": 10, - "level_exp": 1200 - }, { - "level": 11, - "level_exp": 1600 - }, { - "level": 12, - "level_exp": 2100 - }, { - "level": 13, - "level_exp": 2700 - }, { - "level": 14, - "level_exp": 3400 - }, { - "level": 15, - "level_exp": 4200 - }, { - "level": 16, - "level_exp": 5100 - }, { - "level": 17, - "level_exp": 6100 - }, { - "level": 18, - "level_exp": 7200 - }, { - "level": 19, - "level_exp": 8500 - }, { - "level": 20, - "level_exp": 10000 - }, { - "level": 21, - "level_exp": 11500 - }, { - "level": 22, - "level_exp": 13000 - }, { - "level": 23, - "level_exp": 14500 - }, { - "level": 24, - "level_exp": 16000 - }, { - "level": 25, - "level_exp": 17500 - }, { - "level": 26, - "level_exp": 19000 - }, { - "level": 27, - "level_exp": 20500 - }, { - "level": 28, - "level_exp": 22000 - }, { - "level": 29, - "level_exp": 23500 - }, { - "level": 30, - "level_exp": 25000 - }], - "world_ranking_enabled": False, - "is_byd_chapter_unlocked": True - } - }, { - "id": 4, - "value": [] - }, { - "id": 5, - "value": { - "current_map": server.arcworld.get_current_map(user_id), - "user_id": user_id, - "maps": server.arcworld.get_world_all(user_id) - } - } - ]} - - conn.commit() - conn.close() - return r +import sqlite3 +import server.arcworld + + +def int2b(x): + # int与布尔值转换 + if x is None or x == 0: + return False + else: + return True + + +def get_recent_score(c, user_id): + # 得到用户最近一次的成绩,返回列表 + c.execute('''select * from user where user_id = :x''', {'x': user_id}) + x = c.fetchone() + if x is not None: + if x[11] is not None: + c.execute('''select best_clear_type from best_score where user_id=:u and song_id=:s and difficulty=:d''', { + 'u': user_id, 's': x[11], 'd': x[12]}) + y = c.fetchone() + if y is not None: + best_clear_type = y[0] + else: + best_clear_type = x[21] + + return [{ + "rating": x[22], + "modifier": x[19], + "time_played": x[20], + "health": x[18], + "best_clear_type": best_clear_type, + "clear_type": x[21], + "miss_count": x[17], + "near_count": x[16], + "perfect_count": x[15], + "shiny_perfect_count": x[14], + "score": x[13], + "difficulty": x[12], + "song_id": x[11] + }] + return [] + + +def get_user_character(c, user_id): + # 得到用户拥有的角色列表,返回列表 + c.execute('''select * from user_char where user_id = :user_id''', + {'user_id': user_id}) + x = c.fetchall() + if x != []: + s = [] + for i in x: + char_name = '' + c.execute( + '''select name from character where character_id = :x''', {'x': i[1]}) + y = c.fetchone() + if y is not None: + char_name = y[0] + s.append({ + "is_uncapped_override": int2b(i[14]), + "is_uncapped": int2b(i[13]), + "uncap_cores": [], + "char_type": i[12], + "skill_id_uncap": i[11], + "skill_requires_uncap": int2b(i[10]), + "skill_unlock_level": i[9], + "skill_id": i[8], + "overdrive": i[7], + "prog": i[6], + "frag": i[5], + "level_exp": i[4], + "exp": i[3], + "level": i[2], + "name": char_name, + "character_id": i[1] + }) + + return s + else: + return [] + + +def get_user_friend(c, user_id): + # 得到用户的朋友列表,返回列表 + c.execute('''select user_id_other from friend where user_id_me = :user_id''', { + 'user_id': user_id}) + x = c.fetchall() + s = [] + if x != [] and x[0][0] is not None: + + for i in x: + c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''', + {'x': i[0], 'y': user_id}) + if c.fetchone() == (1,): + is_mutual = True + else: + is_mutual = False + + c.execute('''select * from user where user_id = :x''', {'x': i[0]}) + y = c.fetchone() + if y is not None: + s.append({ + "is_mutual": is_mutual, + "is_char_uncapped_override": int2b(y[9]), + "is_char_uncapped": int2b(y[8]), + "is_skill_sealed": int2b(y[7]), + "rating": y[5], + "join_date": int(y[3]), + "character": y[6], + "recent_score": get_recent_score(c, i[0]), + "name": y[1], + "user_id": i[0] + }) + + return s + + +def get_value_0(c, user_id): + # 构造value id=0的数据,返回字典 + c.execute('''select * from user where user_id = :x''', {'x': user_id}) + x = c.fetchone() + r = {} + if x is not None: + user_character = get_user_character(c, user_id) + characters = [] + for i in user_character: + characters.append(i['character_id']) + + r = {"is_aprilfools": False, + "curr_available_maps": [], + "character_stats": user_character, + "friends": get_user_friend(c, user_id), + "settings": { + "favorite_character": x[23], + "is_hide_rating": int2b(x[10]), + "max_stamina_notification_enabled": int2b(x[24]) + }, + "user_id": user_id, + "name": x[1], + "user_code": x[4], + "display_name": x[1], + "ticket": 114514, + "character": x[6], + "is_locked_name_duplicate": False, + "is_skill_sealed": int2b(x[7]), + "current_map": x[25], + "prog_boost": 0, + "next_fragstam_ts": -1, + "max_stamina_ts": 1586274871917, + "stamina": 12, + "world_unlocks": [], + "world_songs": ["babaroque", "shadesoflight", "kanagawa", "lucifer", "anokumene", "ignotus", "rabbitintheblackroom", "qualia", "redandblue", "bookmaker", "darakunosono", "espebranch", "blacklotus", "givemeanightmare", "vividtheory", "onefr", "gekka", "vexaria3", "infinityheaven3", "fairytale3", "goodtek3", "suomi", "rugie", "faintlight", "harutopia", "goodtek", "dreaminattraction", "syro", "diode", "freefall", "grimheart", "blaster", "cyberneciacatharsis", "monochromeprincess", "revixy", "vector", "supernova", "nhelv", "purgatorium3", "dement3", "crossover", "guardina", "axiumcrisis", "worldvanquisher", "sheriruth", "pragmatism", "gloryroad", "etherstrike", "corpssansorganes", "lostdesire", "blrink", "essenceoftwilight", "lapis"], + "singles": ["dataerror", "yourvoiceso", "crosssoul", "impurebird", "auxesia", "modelista", "yozakurafubuki", "surrender", "metallicpunisher", "carminescythe", "bethere", "callmyname", "fallensquare", "dropdead", "alexandrite", "astraltale", "phantasia", "empireofwinter", "libertas", "dottodot", "dreadnought", "mirzam", "heavenlycaress", "filament", "avantraze", "battlenoone", "saikyostronger", "izana", "einherjar", "laqryma", "amygdata", "altale", "feelssoright", "scarletcage", "teriqma", "mahoroba", "badtek", "maliciousmischance", "buchigireberserker", "galaxyfriends", "buchigireberserker2", "xeraphinite"], + "packs": ["vs", "extend", "dynamix", "prelude", "core", "yugamu", "omatsuri", "zettai", "mirai", "shiawase", "chunithm", "nijuusei", "groovecoaster", "rei", "tonesphere", "lanota"], + "characters": characters, + "cores": [], + "recent_score": get_recent_score(c, user_id), + "max_friend": 50, + "rating": x[5], + "join_date": int(x[3]) + } + + return r + + +def arc_aggregate_small(user_id): + # 返回用户数据 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + r = {"success": True, + "value": [{ + "id": 0, + "value": get_value_0(c, user_id) + }]} + + conn.commit() + conn.close() + return r + + +def arc_aggregate_big(user_id): + # 返回用户数据和地图歌曲信息 + # 因为没有整理地图和曲包数据(不需要世界模式),所以直接复制了 + + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + r = {"success": True, + "value": [{ + "id": 0, + "value": get_value_0(c, user_id) + }, { + "id": 1, + "value": [{ + "name": "core", + "items": [{ + "id": "core", + "type": "pack", + "is_available": True + }], + "price": 500, + "orig_price": 500, + "discount_from": 1583712000000, + "discount_to": 1584316799000 + }, { + "name": "shiawase", + "items": [{ + "id": "shiawase", + "type": "pack", + "is_available": True + }, { + "id": "kou", + "type": "character", + "is_available": True + }], + "price": 500, + "orig_price": 500, + "discount_from": 1552089600000, + "discount_to": 1552694399000 + }, { + "name": "dynamix", + "items": [{ + "id": "dynamix", + "type": "pack", + "is_available": True + }, { + "id": "sapphire", + "type": "character", + "is_available": True + }], + "price": 500, + "orig_price": 500, + "discount_from": 1583712000000, + "discount_to": 1584316799000 + }, { + "name": "mirai", + "items": [{ + "id": "mirai", + "type": "pack", + "is_available": True + }, { + "id": "lethe", + "type": "character", + "is_available": True + }], + "price": 500, + "orig_price": 500, + "discount_from": 1552089600000, + "discount_to": 1552694399000 + }, { + "name": "yugamu", + "items": [{ + "id": "yugamu", + "type": "pack", + "is_available": True + }], + "price": 500, + "orig_price": 500, + "discount_from": 1583712000000, + "discount_to": 1584316799000 + }, { + "name": "lanota", + "items": [{ + "id": "lanota", + "type": "pack", + "is_available": True + }], + "price": 500, + "orig_price": 500, + "discount_from": 1583712000000, + "discount_to": 1584316799000 + }, { + "name": "nijuusei", + "items": [{ + "id": "nijuusei", + "type": "pack", + "is_available": True + }], + "price": 500, + "orig_price": 500, + "discount_from": 1583712000000, + "discount_to": 1584316799000 + }, { + "name": "rei", + "items": [{ + "id": "rei", + "type": "pack", + "is_available": True + }], + "price": 500, + "orig_price": 500, + "discount_from": 1583712000000, + "discount_to": 1584316799000 + }, { + "name": "tonesphere", + "items": [{ + "id": "tonesphere", + "type": "pack", + "is_available": True + }], + "price": 500, + "orig_price": 500, + "discount_from": 1583712000000, + "discount_to": 1584316799000 + }, { + "name": "groovecoaster", + "items": [{ + "id": "groovecoaster", + "type": "pack", + "is_available": True + }], + "price": 500, + "orig_price": 500, + "discount_from": 1583712000000, + "discount_to": 1584316799000 + }, { + "name": "zettai", + "items": [{ + "id": "zettai", + "type": "pack", + "is_available": True + }], + "price": 500, + "orig_price": 500, + "discount_from": 1583712000000, + "discount_to": 1584316799000 + }, { + "name": "chunithm", + "items": [{ + "id": "chunithm", + "type": "pack", + "is_available": True + }], + "price": 300, + "orig_price": 300 + }, { + "name": "prelude", + "items": [{ + "id": "prelude", + "type": "pack", + "is_available": True + }], + "price": 400, + "orig_price": 400 + }, { + "name": "omatsuri", + "items": [{ + "id": "omatsuri", + "type": "pack", + "is_available": True + }], + "price": 500, + "orig_price": 500 + }, { + "name": "vs", + "items": [{ + "id": "vs", + "type": "pack", + "is_available": True + }], + "price": 500, + "orig_price": 500 + }, { + "name": "extend", + "items": [{ + "id": "extend", + "type": "pack", + "is_available": True + }], + "price": 700, + "orig_price": 700 + }] + }, { + "id": 2, + "value": {} + }, { + "id": 3, + "value": { + "max_stamina": 12, + "stamina_recover_tick": 1800000, + "core_exp": 250, + "curr_ts": 1599547606825, + "level_steps": [{ + "level": 1, + "level_exp": 0 + }, { + "level": 2, + "level_exp": 50 + }, { + "level": 3, + "level_exp": 100 + }, { + "level": 4, + "level_exp": 150 + }, { + "level": 5, + "level_exp": 200 + }, { + "level": 6, + "level_exp": 300 + }, { + "level": 7, + "level_exp": 450 + }, { + "level": 8, + "level_exp": 650 + }, { + "level": 9, + "level_exp": 900 + }, { + "level": 10, + "level_exp": 1200 + }, { + "level": 11, + "level_exp": 1600 + }, { + "level": 12, + "level_exp": 2100 + }, { + "level": 13, + "level_exp": 2700 + }, { + "level": 14, + "level_exp": 3400 + }, { + "level": 15, + "level_exp": 4200 + }, { + "level": 16, + "level_exp": 5100 + }, { + "level": 17, + "level_exp": 6100 + }, { + "level": 18, + "level_exp": 7200 + }, { + "level": 19, + "level_exp": 8500 + }, { + "level": 20, + "level_exp": 10000 + }, { + "level": 21, + "level_exp": 11500 + }, { + "level": 22, + "level_exp": 13000 + }, { + "level": 23, + "level_exp": 14500 + }, { + "level": 24, + "level_exp": 16000 + }, { + "level": 25, + "level_exp": 17500 + }, { + "level": 26, + "level_exp": 19000 + }, { + "level": 27, + "level_exp": 20500 + }, { + "level": 28, + "level_exp": 22000 + }, { + "level": 29, + "level_exp": 23500 + }, { + "level": 30, + "level_exp": 25000 + }], + "world_ranking_enabled": False, + "is_byd_chapter_unlocked": True + } + }, { + "id": 4, + "value": [] + }, { + "id": 5, + "value": { + "current_map": server.arcworld.get_current_map(user_id), + "user_id": user_id, + "maps": server.arcworld.get_world_all(user_id) + } + } + ]} + + conn.commit() + conn.close() + return r diff --git a/v1.3/server/setme.py b/latest version/server/setme.py similarity index 97% rename from v1.3/server/setme.py rename to latest version/server/setme.py index 0891803..4512782 100644 --- a/v1.3/server/setme.py +++ b/latest version/server/setme.py @@ -1,155 +1,155 @@ -import sqlite3 -import server.info - - -def b2int(x): - # int与布尔值转换 - if x: - return 1 - else: - return 0 - - -def int2b(x): - # int与布尔值转换 - if x is None or x == 0: - return False - else: - return True - - -def change_char(user_id, character_id, skill_sealed): - # 角色改变,包括技能封印的改变,返回成功与否的布尔值 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''', - {'a': user_id, 'b': character_id}) - x = c.fetchone() - if x is not None: - if skill_sealed == 'false': - skill_sealed = False - else: - skill_sealed = True - c.execute('''update user set is_skill_sealed = :a, character_id = :b, is_char_uncapped = :c, is_char_uncapped_override = :d where user_id = :e''', { - 'a': b2int(skill_sealed), 'b': character_id, 'c': x[0], 'd': x[1], 'e': user_id}) - - conn.commit() - conn.close() - return True - - conn.commit() - conn.close() - return False - - -def change_char_uncap(user_id, character_id): - # 角色觉醒改变,返回字典 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''', - {'a': user_id, 'b': character_id}) - x = c.fetchone() - r = None - if x is not None and x[0] == 1: - c.execute('''update user set is_char_uncapped_override = :a where user_id = :b''', { - 'a': b2int(x[1] == 0), 'b': user_id}) - c.execute('''update user_char set is_uncapped_override = :a where user_id = :b and character_id = :c''', { - 'a': b2int(x[1] == 0), 'b': user_id, 'c': character_id}) - c.execute('''select * from user_char where user_id = :a and character_id = :b''', - {'a': user_id, 'b': character_id}) - y = c.fetchone() - c.execute( - '''select name from character where character_id = :x''', {'x': y[1]}) - z = c.fetchone() - if z is not None: - char_name = z[0] - if y is not None: - r = { - "is_uncapped_override": int2b(y[14]), - "is_uncapped": int2b(y[13]), - "uncap_cores": [], - "char_type": y[12], - "skill_id_uncap": y[11], - "skill_requires_uncap": int2b(y[10]), - "skill_unlock_level": y[9], - "skill_id": y[8], - "overdrive": y[7], - "prog": y[6], - "frag": y[5], - "level_exp": y[4], - "exp": y[3], - "level": y[2], - "name": char_name, - "character_id": y[1] - } - - conn.commit() - conn.close() - return r - - -def arc_sys_set(user_id, value, set_arg): - # 三个设置,PTT隐藏、体力满通知、最爱角色,无返回 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - if 'favorite_character' in set_arg: - value = int(value) - c.execute('''update user set favorite_character = :a where user_id = :b''', { - 'a': value, 'b': user_id}) - - else: - if value == 'false': - value = False - else: - value = True - - if 'is_hide_rating' in set_arg: - c.execute('''update user set is_hide_rating = :a where user_id = :b''', { - 'a': b2int(value), 'b': user_id}) - if 'max_stamina_notification_enabled' in set_arg: - c.execute('''update user set max_stamina_notification_enabled = :a where user_id = :b''', { - 'a': b2int(value), 'b': user_id}) - - conn.commit() - conn.close() - return None - - -def arc_add_friend(user_id, friend_id): - # 加好友,返回好友列表,或者是错误码602、604 - if user_id == friend_id: - return 604 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''', - {'x': user_id, 'y': friend_id}) - r = None - if c.fetchone() == (0,): - c.execute('''insert into friend values(:a, :b)''', - {'a': user_id, 'b': friend_id}) - r = server.info.get_user_friend(c, user_id) - - else: - return 602 - - conn.commit() - conn.close() - return r - - -def arc_delete_friend(user_id, friend_id): - # 删好友,返回好友列表 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''', - {'x': user_id, 'y': friend_id}) - r = None - if c.fetchone() == (1,): - c.execute('''delete from friend where user_id_me = :x and user_id_other = :y''', - {'x': user_id, 'y': friend_id}) - - r = server.info.get_user_friend(c, user_id) - - conn.commit() - conn.close() - return r +import sqlite3 +import server.info + + +def b2int(x): + # int与布尔值转换 + if x: + return 1 + else: + return 0 + + +def int2b(x): + # int与布尔值转换 + if x is None or x == 0: + return False + else: + return True + + +def change_char(user_id, character_id, skill_sealed): + # 角色改变,包括技能封印的改变,返回成功与否的布尔值 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''', + {'a': user_id, 'b': character_id}) + x = c.fetchone() + if x is not None: + if skill_sealed == 'false': + skill_sealed = False + else: + skill_sealed = True + c.execute('''update user set is_skill_sealed = :a, character_id = :b, is_char_uncapped = :c, is_char_uncapped_override = :d where user_id = :e''', { + 'a': b2int(skill_sealed), 'b': character_id, 'c': x[0], 'd': x[1], 'e': user_id}) + + conn.commit() + conn.close() + return True + + conn.commit() + conn.close() + return False + + +def change_char_uncap(user_id, character_id): + # 角色觉醒改变,返回字典 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''', + {'a': user_id, 'b': character_id}) + x = c.fetchone() + r = None + if x is not None and x[0] == 1: + c.execute('''update user set is_char_uncapped_override = :a where user_id = :b''', { + 'a': b2int(x[1] == 0), 'b': user_id}) + c.execute('''update user_char set is_uncapped_override = :a where user_id = :b and character_id = :c''', { + 'a': b2int(x[1] == 0), 'b': user_id, 'c': character_id}) + c.execute('''select * from user_char where user_id = :a and character_id = :b''', + {'a': user_id, 'b': character_id}) + y = c.fetchone() + c.execute( + '''select name from character where character_id = :x''', {'x': y[1]}) + z = c.fetchone() + if z is not None: + char_name = z[0] + if y is not None: + r = { + "is_uncapped_override": int2b(y[14]), + "is_uncapped": int2b(y[13]), + "uncap_cores": [], + "char_type": y[12], + "skill_id_uncap": y[11], + "skill_requires_uncap": int2b(y[10]), + "skill_unlock_level": y[9], + "skill_id": y[8], + "overdrive": y[7], + "prog": y[6], + "frag": y[5], + "level_exp": y[4], + "exp": y[3], + "level": y[2], + "name": char_name, + "character_id": y[1] + } + + conn.commit() + conn.close() + return r + + +def arc_sys_set(user_id, value, set_arg): + # 三个设置,PTT隐藏、体力满通知、最爱角色,无返回 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + if 'favorite_character' in set_arg: + value = int(value) + c.execute('''update user set favorite_character = :a where user_id = :b''', { + 'a': value, 'b': user_id}) + + else: + if value == 'false': + value = False + else: + value = True + + if 'is_hide_rating' in set_arg: + c.execute('''update user set is_hide_rating = :a where user_id = :b''', { + 'a': b2int(value), 'b': user_id}) + if 'max_stamina_notification_enabled' in set_arg: + c.execute('''update user set max_stamina_notification_enabled = :a where user_id = :b''', { + 'a': b2int(value), 'b': user_id}) + + conn.commit() + conn.close() + return None + + +def arc_add_friend(user_id, friend_id): + # 加好友,返回好友列表,或者是错误码602、604 + if user_id == friend_id: + return 604 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''', + {'x': user_id, 'y': friend_id}) + r = None + if c.fetchone() == (0,): + c.execute('''insert into friend values(:a, :b)''', + {'a': user_id, 'b': friend_id}) + r = server.info.get_user_friend(c, user_id) + + else: + return 602 + + conn.commit() + conn.close() + return r + + +def arc_delete_friend(user_id, friend_id): + # 删好友,返回好友列表 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''', + {'x': user_id, 'y': friend_id}) + r = None + if c.fetchone() == (1,): + c.execute('''delete from friend where user_id_me = :x and user_id_other = :y''', + {'x': user_id, 'y': friend_id}) + + r = server.info.get_user_friend(c, user_id) + + conn.commit() + conn.close() + return r diff --git a/v1.3/setting.ini b/latest version/setting.ini similarity index 95% rename from v1.3/setting.ini rename to latest version/setting.ini index 3d109b5..f9e9a63 100644 --- a/v1.3/setting.ini +++ b/latest version/setting.ini @@ -1,3 +1,3 @@ -[CONFIG] -HOST = 192.168.1.113 +[CONFIG] +HOST = 192.168.1.113 PORT = 80 \ No newline at end of file diff --git a/v1.3/static/style.css b/latest version/static/style.css similarity index 93% rename from v1.3/static/style.css rename to latest version/static/style.css index c486e03..758a6b3 100644 --- a/v1.3/static/style.css +++ b/latest version/static/style.css @@ -1,217 +1,217 @@ -html { - font-family: sans-serif; - background: #eee; - padding: 1rem; -} - -body { - max-width: 960px; - margin: 0 auto; - background: white; -} - -h1 { - font-family: serif; - color: #377ba8; - margin: 1rem 0; -} - -a { - text-decoration: none; - color: #377ba8; -} - -hr { - border: none; - border-top: 1px solid lightgray; -} - -nav { - background: lightgray; - display: flex; - align-items: center; - padding: 0 0.5rem; -} - -nav h1 { - flex: auto; - margin: 0; -} - -nav h1 a { - text-decoration: none; - padding: 0.25rem 0.5rem; -} - -nav ul { - display: flex; - list-style: none; - margin: 0; - padding: 0; -} - -nav ul li a, -nav ul li span, -header .action { - display: block; - padding: 0.5rem; -} - -.content { - padding: 0 1rem 1rem; -} - -.content>header { - border-bottom: 1px solid lightgray; - display: flex; - align-items: flex-end; -} - -.content>header h1 { - flex: auto; - margin: 1rem 0 0.25rem 0; -} - -.flash { - margin: 1em 0; - padding: 1em; - background: #cae6f6; - border: 1px solid #377ba8; -} - -.post>header { - display: flex; - align-items: flex-end; - font-size: 0.85em; -} - -.post>header>div:first-of-type { - flex: auto; -} - -.post>header h1 { - font-size: 1.5em; - margin-bottom: 0; -} - -.post .about { - color: slategray; - font-style: italic; -} - -.post .body { - white-space: pre-line; -} - -.content:last-child { - margin-bottom: 0; -} - -.content form { - margin: 1em 0; - display: flex; - flex-direction: column; -} - -.content label { - font-weight: bold; - margin-bottom: 0.5em; -} - -.content input, -.content textarea { - margin-bottom: 1em; -} - -.content textarea { - min-height: 12em; - resize: vertical; -} - -input.danger { - color: #cc2f2e; -} - -input[type=submit] { - align-self: start; - min-width: 10em; -} - - -.score-item { - margin-bottom: 10px; - clear: both; -} - -.song-title { - font-size: 1.3em; - font-weight: bold; - display: inline-block; -} - -.difficulty_pst { - font-size: 0.9em; - background-color: rgb(10, 130, 190); - color: white; -} - -.difficulty_prs { - font-size: 0.9em; - background-color: rgb(100, 140, 60); - color: white; -} - -.difficulty_ftr { - font-size: 0.9em; - background-color: rgb(80, 25, 75); - color: white; -} - -.difficulty_byd { - font-size: 0.9em; - background-color: rgb(130, 35, 40); - color: white; -} - -.rank { - font-size: 0.8em; - margin-left: 4px; - padding: 0 4px; -} - -.rank_big { - font-size: 1.2em; - margin-left: 4px; - padding: 0 4px; -} - -.song-detail { - font-size: 0.8em; - float: right; - text-align: right; -} - -.song-score { - font-size: 1.375em; - font-family: Arial; -} - -.song-clear-type { - font-size: 0.875em; - padding-left: 0.625em; -} - -.title { - font-size: 1.375em; -} - -.name { - font-size: 1.12em; - font-weight: bold; -} - -.footer{ - font-size: 0.5em; - color: grey; - text-align: center; +html { + font-family: sans-serif; + background: #eee; + padding: 1rem; +} + +body { + max-width: 960px; + margin: 0 auto; + background: white; +} + +h1 { + font-family: serif; + color: #377ba8; + margin: 1rem 0; +} + +a { + text-decoration: none; + color: #377ba8; +} + +hr { + border: none; + border-top: 1px solid lightgray; +} + +nav { + background: lightgray; + display: flex; + align-items: center; + padding: 0 0.5rem; +} + +nav h1 { + flex: auto; + margin: 0; +} + +nav h1 a { + text-decoration: none; + padding: 0.25rem 0.5rem; +} + +nav ul { + display: flex; + list-style: none; + margin: 0; + padding: 0; +} + +nav ul li a, +nav ul li span, +header .action { + display: block; + padding: 0.5rem; +} + +.content { + padding: 0 1rem 1rem; +} + +.content>header { + border-bottom: 1px solid lightgray; + display: flex; + align-items: flex-end; +} + +.content>header h1 { + flex: auto; + margin: 1rem 0 0.25rem 0; +} + +.flash { + margin: 1em 0; + padding: 1em; + background: #cae6f6; + border: 1px solid #377ba8; +} + +.post>header { + display: flex; + align-items: flex-end; + font-size: 0.85em; +} + +.post>header>div:first-of-type { + flex: auto; +} + +.post>header h1 { + font-size: 1.5em; + margin-bottom: 0; +} + +.post .about { + color: slategray; + font-style: italic; +} + +.post .body { + white-space: pre-line; +} + +.content:last-child { + margin-bottom: 0; +} + +.content form { + margin: 1em 0; + display: flex; + flex-direction: column; +} + +.content label { + font-weight: bold; + margin-bottom: 0.5em; +} + +.content input, +.content textarea { + margin-bottom: 1em; +} + +.content textarea { + min-height: 12em; + resize: vertical; +} + +input.danger { + color: #cc2f2e; +} + +input[type=submit] { + align-self: start; + min-width: 10em; +} + + +.score-item { + margin-bottom: 10px; + clear: both; +} + +.song-title { + font-size: 1.3em; + font-weight: bold; + display: inline-block; +} + +.difficulty_pst { + font-size: 0.9em; + background-color: rgb(10, 130, 190); + color: white; +} + +.difficulty_prs { + font-size: 0.9em; + background-color: rgb(100, 140, 60); + color: white; +} + +.difficulty_ftr { + font-size: 0.9em; + background-color: rgb(80, 25, 75); + color: white; +} + +.difficulty_byd { + font-size: 0.9em; + background-color: rgb(130, 35, 40); + color: white; +} + +.rank { + font-size: 0.8em; + margin-left: 4px; + padding: 0 4px; +} + +.rank_big { + font-size: 1.2em; + margin-left: 4px; + padding: 0 4px; +} + +.song-detail { + font-size: 0.8em; + float: right; + text-align: right; +} + +.song-score { + font-size: 1.375em; + font-family: Arial; +} + +.song-clear-type { + font-size: 0.875em; + padding-left: 0.625em; +} + +.title { + font-size: 1.375em; +} + +.name { + font-size: 1.12em; + font-weight: bold; +} + +.footer{ + font-size: 0.5em; + color: grey; + text-align: center; } \ No newline at end of file diff --git a/v1.3/templates/base.html b/latest version/templates/base.html similarity index 97% rename from v1.3/templates/base.html rename to latest version/templates/base.html index 160c5d0..17dc77e 100644 --- a/v1.3/templates/base.html +++ b/latest version/templates/base.html @@ -1,23 +1,23 @@ - -{% block title %}{% endblock %} - Arcaea Server - - -
-
- {% block header %}{% endblock %} -
- {% for message in get_flashed_messages() %} -
{{ message }}
- {% endfor %} {% block content %}{% endblock %} -
- + +{% block title %}{% endblock %} - Arcaea Server + + +
+
+ {% block header %}{% endblock %} +
+ {% for message in get_flashed_messages() %} +
{{ message }}
+ {% endfor %} {% block content %}{% endblock %} +
+
Made by Lost@2020
\ No newline at end of file diff --git a/v1.3/templates/web/allplayer.html b/latest version/templates/web/allplayer.html similarity index 97% rename from v1.3/templates/web/allplayer.html rename to latest version/templates/web/allplayer.html index 9dd4437..439a437 100644 --- a/v1.3/templates/web/allplayer.html +++ b/latest version/templates/web/allplayer.html @@ -1,81 +1,81 @@ -{% extends 'base.html' %} -{% block header %} -

{% block title %}All players{% endblock %}

-{% endblock %} - -{% block content %} -{% if posts %} -{% for user in posts %} - -
-
{{user['name']}} - UID: {{user['user_id']}} - User code: {{user['user_code']}} -
-
注册于 Registered in: {{user['join_date']}}
-
PTT: {{user['rating_ptt']//100 ~ '.' ~ user['rating_ptt']%100}}
-
-
Recent plays:
-
-
- - {{user['song_id']}} - - {% if user['difficulty'] == 0 %} - PST - {% elif user['difficulty'] == 1 %} - PRS - {% elif user['difficulty'] == 2 %} - FTR - {% else %} - BYD - {% endif %} - -
-
- - - - - - - - - - - - - - - - - - -
PURE: {{user['perfect_count']}} {{'(' ~ user['shiny_perfect_count'] ~ ')'}}
FAR: {{user['near_count']}}
LOST: {{user['miss_count']}}
-
-
{{user['score']}}
-
- {% if user['clear_type'] == 3 %}Pure Memory - {% elif user['clear_type'] == 2 %}Full Recall - {% elif user['clear_type'] == 5 %}Hard Clear - {% elif user['clear_type'] == 1 %}Normal Clear - {% elif user['clear_type'] == 4 %}Easy Clear - {% else%}Track Lost - {% endif %} -
-
成绩评价 Rating: {{user['rating']}}
-
日期 Date: - {{user['time_played']}} -
-
-
-
-
-{% if not loop.last %} -
-
-{% endif %} -{% endfor %} - -{% endif %} +{% extends 'base.html' %} +{% block header %} +

{% block title %}All players{% endblock %}

+{% endblock %} + +{% block content %} +{% if posts %} +{% for user in posts %} + +
+
{{user['name']}} + UID: {{user['user_id']}} + User code: {{user['user_code']}} +
+
注册于 Registered in: {{user['join_date']}}
+
PTT: {{user['rating_ptt']//100 ~ '.' ~ user['rating_ptt']%100}}
+
+
Recent plays:
+
+
+ + {{user['song_id']}} + + {% if user['difficulty'] == 0 %} + PST + {% elif user['difficulty'] == 1 %} + PRS + {% elif user['difficulty'] == 2 %} + FTR + {% else %} + BYD + {% endif %} + +
+
+ + + + + + + + + + + + + + + + + + +
PURE: {{user['perfect_count']}} {{'(' ~ user['shiny_perfect_count'] ~ ')'}}
FAR: {{user['near_count']}}
LOST: {{user['miss_count']}}
+
+
{{user['score']}}
+
+ {% if user['clear_type'] == 3 %}Pure Memory + {% elif user['clear_type'] == 2 %}Full Recall + {% elif user['clear_type'] == 5 %}Hard Clear + {% elif user['clear_type'] == 1 %}Normal Clear + {% elif user['clear_type'] == 4 %}Easy Clear + {% else%}Track Lost + {% endif %} +
+
成绩评价 Rating: {{user['rating']}}
+
日期 Date: + {{user['time_played']}} +
+
+
+
+
+{% if not loop.last %} +
+
+{% endif %} +{% endfor %} + +{% endif %} {% endblock %} \ No newline at end of file diff --git a/v1.3/templates/web/allsong.html b/latest version/templates/web/allsong.html similarity index 96% rename from v1.3/templates/web/allsong.html rename to latest version/templates/web/allsong.html index 4aab965..8df9a87 100644 --- a/v1.3/templates/web/allsong.html +++ b/latest version/templates/web/allsong.html @@ -1,48 +1,48 @@ -{% extends 'base.html' %} -{% block header %} -

{% block title %}All songs{% endblock %}

-{% endblock %} - -{% block content %} -{% if posts %}
-{% for song in posts %} - -
- Sid: - {{song['song_id']}} -
- Name_en: - {{song['name_en']}} -
-
铺面定数 Chart const:
- {% if song['rating_pst'] %} - PST - {{song['rating_pst']}} - {% endif %} -
- {% if song['rating_prs'] %} - PRS - {{song['rating_prs']}} - {% endif %} -
- {% if song['rating_ftr'] %} - FTR - {{song['rating_ftr']}} - {% endif %} -
- {% if song['rating_byn'] %} - BYD - {{song['rating_byn']}} - {% endif %} - - -
-{% if not loop.last %} -
-
-
-{% endif %} -{% endfor %} - -{% endif %} +{% extends 'base.html' %} +{% block header %} +

{% block title %}All songs{% endblock %}

+{% endblock %} + +{% block content %} +{% if posts %}
+{% for song in posts %} + +
+ Sid: + {{song['song_id']}} +
+ Name_en: + {{song['name_en']}} +
+
铺面定数 Chart const:
+ {% if song['rating_pst'] %} + PST + {{song['rating_pst']}} + {% endif %} +
+ {% if song['rating_prs'] %} + PRS + {{song['rating_prs']}} + {% endif %} +
+ {% if song['rating_ftr'] %} + FTR + {{song['rating_ftr']}} + {% endif %} +
+ {% if song['rating_byn'] %} + BYD + {{song['rating_byn']}} + {% endif %} + + +
+{% if not loop.last %} +
+
+
+{% endif %} +{% endfor %} + +{% endif %} {% endblock %} \ No newline at end of file diff --git a/v1.3/templates/web/changesong.html b/latest version/templates/web/changesong.html similarity index 97% rename from v1.3/templates/web/changesong.html rename to latest version/templates/web/changesong.html index e03eb5a..c9f9219 100644 --- a/v1.3/templates/web/changesong.html +++ b/latest version/templates/web/changesong.html @@ -1,35 +1,35 @@ -{% extends 'base.html' %} -{% block header %} -

{% block title %}Change the songs{% endblock %}

-{% endblock %} - -{% block content %} -
-
Add the song
- - - - - - - - - - - - - -
如果没有某个铺面,应该填入-1。
-
If there is no some chart, fill in -1 please.
- -
-
-
-
-
Delete the song
- - - - -
+{% extends 'base.html' %} +{% block header %} +

{% block title %}Change the songs{% endblock %}

+{% endblock %} + +{% block content %} +
+
Add the song
+ + + + + + + + + + + + + +
如果没有某个铺面,应该填入-1。
+
If there is no some chart, fill in -1 please.
+ +
+
+
+
+
Delete the song
+ + + + +
{% endblock %} \ No newline at end of file diff --git a/v1.3/templates/web/index.html b/latest version/templates/web/index.html similarity index 98% rename from v1.3/templates/web/index.html rename to latest version/templates/web/index.html index bd62a7e..2b80347 100644 --- a/v1.3/templates/web/index.html +++ b/latest version/templates/web/index.html @@ -1,24 +1,24 @@ -{% extends 'base.html' %} -{% block header %} -

{% block title %}Index{% endblock %}

-{% endblock %} - -{% block content %} -

说明 Statement

-

这是Arcaea Server的后台管理协助系统,可以进行一些简单的操作
- This is the background management assistance system of Arcaea Server, which can be used to do some simple - operations. -

-

游戏方面 Game

-单个玩家成绩查询 Single player score

-单个玩家PTT详情查询 Single player ptt

-所有玩家信息查询 All players

-铺面信息查询 All songs

-单个铺面排行榜查询 Single song chart tops -
-

系统方面 System

-数据库更新 Update databases

-歌曲修改 Change the songs - - +{% extends 'base.html' %} +{% block header %} +

{% block title %}Index{% endblock %}

+{% endblock %} + +{% block content %} +

说明 Statement

+

这是Arcaea Server的后台管理协助系统,可以进行一些简单的操作
+ This is the background management assistance system of Arcaea Server, which can be used to do some simple + operations. +

+

游戏方面 Game

+单个玩家成绩查询 Single player score

+单个玩家PTT详情查询 Single player ptt

+所有玩家信息查询 All players

+铺面信息查询 All songs

+单个铺面排行榜查询 Single song chart tops +
+

系统方面 System

+数据库更新 Update databases

+歌曲修改 Change the songs + + {% endblock %} \ No newline at end of file diff --git a/v1.3/templates/web/login.html b/latest version/templates/web/login.html similarity index 96% rename from v1.3/templates/web/login.html rename to latest version/templates/web/login.html index b8ee233..8af83c8 100644 --- a/v1.3/templates/web/login.html +++ b/latest version/templates/web/login.html @@ -1,14 +1,14 @@ -{% extends 'base.html' %} -{% block header %} -

{% block title %}Log In{% endblock %}

-{% endblock %} - -{% block content %} -
- - - - - -
+{% extends 'base.html' %} +{% block header %} +

{% block title %}Log In{% endblock %}

+{% endblock %} + +{% block content %} +
+ + + + + +
{% endblock %} \ No newline at end of file diff --git a/v1.3/templates/web/singlecharttop.html b/latest version/templates/web/singlecharttop.html similarity index 97% rename from v1.3/templates/web/singlecharttop.html rename to latest version/templates/web/singlecharttop.html index 9e6a10a..ef7c4d2 100644 --- a/v1.3/templates/web/singlecharttop.html +++ b/latest version/templates/web/singlecharttop.html @@ -1,108 +1,108 @@ -{% extends 'base.html' %} -{% block header %} -

{% block title %}Single chart top{% endblock %}

-{% endblock %} - -{% block content %} -
- - 模糊查询,只返回第一个 - Fuzzy query,and only return the first one. - - - -
- -
-
-
- {% if song_id %} -
- - {{song_id}} - - - {% if difficulty == 0 %} - PST - {% elif difficulty == 1 %} - PRS - {% elif difficulty == 2 %} - FTR - {% else %} - BYD - - {% endif %} -
-
- {{song_name_en}} -
-
- {% endif %} -
-
- {% for post in posts %} -
-
- {{'#' ~ post['rank']}} - - {{post['name']}} - - UID: {{post['user_id']}} -
- -
- - - - - - - - - - - - - - - - - - -
PURE: {{post['perfect_count']}} {{'(' ~ post['shiny_perfect_count'] ~ ')'}}
FAR: {{post['near_count']}}
LOST: {{post['miss_count']}}
-
-
{{post['score']}}
-
- {% if post['clear_type'] == 3 %}Pure Memory - {% elif post['clear_type'] == 2 %}Full Recall - {% elif post['clear_type'] == 5 %}Hard Clear - {% elif post['clear_type'] == 1 %}Normal Clear - {% elif post['clear_type'] == 4 %}Easy Clear - {% else%}Track Lost - {% endif %} - - {% if post['best_clear_type'] == 3 %}(Pure Memory) - {% elif post['best_clear_type'] == 2 %}(Full Recall) - {% elif post['best_clear_type'] == 5 %}(Hard Clear) - {% elif post['best_clear_type'] == 1 %}(Normal Clear) - {% elif post['best_clear_type'] == 4 %}(Easy Clear) - {% else%}(Track Lost) - {% endif %} - -
-
日期 Date: - {{post['time_played']}} -
-
- - {% if not loop.last %} -
- {% endif %} - {% endfor %} -
+{% extends 'base.html' %} +{% block header %} +

{% block title %}Single chart top{% endblock %}

+{% endblock %} + +{% block content %} +
+ + 模糊查询,只返回第一个 + Fuzzy query,and only return the first one. + + + +
+ +
+
+
+ {% if song_id %} +
+ + {{song_id}} + + + {% if difficulty == 0 %} + PST + {% elif difficulty == 1 %} + PRS + {% elif difficulty == 2 %} + FTR + {% else %} + BYD + + {% endif %} +
+
+ {{song_name_en}} +
+
+ {% endif %} +
+
+ {% for post in posts %} +
+
+ {{'#' ~ post['rank']}} + + {{post['name']}} + + UID: {{post['user_id']}} +
+ +
+ + + + + + + + + + + + + + + + + + +
PURE: {{post['perfect_count']}} {{'(' ~ post['shiny_perfect_count'] ~ ')'}}
FAR: {{post['near_count']}}
LOST: {{post['miss_count']}}
+
+
{{post['score']}}
+
+ {% if post['clear_type'] == 3 %}Pure Memory + {% elif post['clear_type'] == 2 %}Full Recall + {% elif post['clear_type'] == 5 %}Hard Clear + {% elif post['clear_type'] == 1 %}Normal Clear + {% elif post['clear_type'] == 4 %}Easy Clear + {% else%}Track Lost + {% endif %} + + {% if post['best_clear_type'] == 3 %}(Pure Memory) + {% elif post['best_clear_type'] == 2 %}(Full Recall) + {% elif post['best_clear_type'] == 5 %}(Hard Clear) + {% elif post['best_clear_type'] == 1 %}(Normal Clear) + {% elif post['best_clear_type'] == 4 %}(Easy Clear) + {% else%}(Track Lost) + {% endif %} + +
+
日期 Date: + {{post['time_played']}} +
+
+ + {% if not loop.last %} +
+ {% endif %} + {% endfor %} +
{% endblock %} \ No newline at end of file diff --git a/v1.3/templates/web/singleplayer.html b/latest version/templates/web/singleplayer.html similarity index 97% rename from v1.3/templates/web/singleplayer.html rename to latest version/templates/web/singleplayer.html index 5289745..9b3c3dc 100644 --- a/v1.3/templates/web/singleplayer.html +++ b/latest version/templates/web/singleplayer.html @@ -1,85 +1,85 @@ -{% extends 'base.html' %} -{% block header %} -

{% block title %}Single player score{% endblock %}

-{% endblock %} - -{% block content %} -
- - - or
- - - -
-
-
- {% for post in posts %} -
- - {{post['song_id']}} - - {% if post['difficulty'] == 0 %} - PST - {% elif post['difficulty'] == 1 %} - PRS - {% elif post['difficulty'] == 2 %} - FTR - {% else %} - BYD - {% endif %} - {{'#' ~ post['rank']}} - -
-
- - - - - - - - - - - - - - - - - - -
PURE: {{post['perfect_count']}} {{'(' ~ post['shiny_perfect_count'] ~ ')'}}
FAR: {{post['near_count']}}
LOST: {{post['miss_count']}}
-
-
{{post['score']}}
-
- {% if post['clear_type'] == 3 %}Pure Memory - {% elif post['clear_type'] == 2 %}Full Recall - {% elif post['clear_type'] == 5 %}Hard Clear - {% elif post['clear_type'] == 1 %}Normal Clear - {% elif post['clear_type'] == 4 %}Easy Clear - {% else%}Track Lost - {% endif %} - - {% if post['best_clear_type'] == 3 %}(Pure Memory) - {% elif post['best_clear_type'] == 2 %}(Full Recall) - {% elif post['best_clear_type'] == 5 %}(Hard Clear) - {% elif post['best_clear_type'] == 1 %}(Normal Clear) - {% elif post['best_clear_type'] == 4 %}(Easy Clear) - {% else%}(Track Lost) - {% endif %} - -
-
成绩评价 Rating: {{post['rating']}}
-
日期 Date: - {{post['time_played']}} -
-
- - {% if not loop.last %} -
- {% endif %} - {% endfor %} -
+{% extends 'base.html' %} +{% block header %} +

{% block title %}Single player score{% endblock %}

+{% endblock %} + +{% block content %} +
+ + + or
+ + + +
+
+
+ {% for post in posts %} +
+ + {{post['song_id']}} + + {% if post['difficulty'] == 0 %} + PST + {% elif post['difficulty'] == 1 %} + PRS + {% elif post['difficulty'] == 2 %} + FTR + {% else %} + BYD + {% endif %} + {{'#' ~ post['rank']}} + +
+
+ + + + + + + + + + + + + + + + + + +
PURE: {{post['perfect_count']}} {{'(' ~ post['shiny_perfect_count'] ~ ')'}}
FAR: {{post['near_count']}}
LOST: {{post['miss_count']}}
+
+
{{post['score']}}
+
+ {% if post['clear_type'] == 3 %}Pure Memory + {% elif post['clear_type'] == 2 %}Full Recall + {% elif post['clear_type'] == 5 %}Hard Clear + {% elif post['clear_type'] == 1 %}Normal Clear + {% elif post['clear_type'] == 4 %}Easy Clear + {% else%}Track Lost + {% endif %} + + {% if post['best_clear_type'] == 3 %}(Pure Memory) + {% elif post['best_clear_type'] == 2 %}(Full Recall) + {% elif post['best_clear_type'] == 5 %}(Hard Clear) + {% elif post['best_clear_type'] == 1 %}(Normal Clear) + {% elif post['best_clear_type'] == 4 %}(Easy Clear) + {% else%}(Track Lost) + {% endif %} + +
+
成绩评价 Rating: {{post['rating']}}
+
日期 Date: + {{post['time_played']}} +
+
+ + {% if not loop.last %} +
+ {% endif %} + {% endfor %} +
{% endblock %} \ No newline at end of file diff --git a/v1.3/templates/web/singleplayerptt.html b/latest version/templates/web/singleplayerptt.html similarity index 97% rename from v1.3/templates/web/singleplayerptt.html rename to latest version/templates/web/singleplayerptt.html index 96d4023..248caf0 100644 --- a/v1.3/templates/web/singleplayerptt.html +++ b/latest version/templates/web/singleplayerptt.html @@ -1,191 +1,191 @@ -{% extends 'base.html' %} -{% block header %} -

{% block title %}Single player ptt{% endblock %}

-{% endblock %} - -{% block content %} -
- - - or
- - - -
-
-
- {% if user %} -
- -
-
玩家信息 Player information
-
{{user['name']}} - UID: {{user['user_id']}} - User code: {{user['user_code']}} -
-
注册于 Registered in: {{user['join_date']}}
-
PTT: {{user['rating_ptt']//100 ~ '.' ~ user['rating_ptt']%100}}
-
Best 30 PTT: {{bestptt}}
-
Recent 10 PTT: {{recentptt}}
-
-
Recent plays:
-
-
- - {{user['song_id']}} - - {% if user['difficulty'] == 0 %} - PST - {% elif user['difficulty'] == 1 %} - PRS - {% elif user['difficulty'] == 2 %} - FTR - {% else %} - BYD - {% endif %} - -
-
- - - - - - - - - - - - - - - - - - -
PURE: {{user['perfect_count']}} {{'(' ~ user['shiny_perfect_count'] ~ ')'}}
FAR: {{user['near_count']}}
LOST: {{user['miss_count']}}
-
-
{{user['score']}}
-
- {% if user['clear_type'] == 3 %}Pure Memory - {% elif user['clear_type'] == 2 %}Full Recall - {% elif user['clear_type'] == 5 %}Hard Clear - {% elif user['clear_type'] == 1 %}Normal Clear - {% elif user['clear_type'] == 4 %}Easy Clear - {% else%}Track Lost - {% endif %} -
-
成绩评价 Rating: {{user['rating']}}
-
日期 Date: - {{user['time_played']}} -
-
-
-
-
-
- {% if posts %} -
Best 30
- {% endif %} - {% for post in posts %} -
- - {{post['song_id']}} - - {% if post['difficulty'] == 0 %} - PST - {% elif post['difficulty'] == 1 %} - PRS - {% elif post['difficulty'] == 2 %} - FTR - {% else %} - BYD - {% endif %} - {{'#' ~ post['rank']}} - -
-
- - - - - - - - - - - - - - - - - - -
PURE: {{post['perfect_count']}} {{'(' ~ post['shiny_perfect_count'] ~ ')'}}
FAR: {{post['near_count']}}
LOST: {{post['miss_count']}}
-
-
{{post['score']}}
-
- {% if post['clear_type'] == 3 %}Pure Memory - {% elif post['clear_type'] == 2 %}Full Recall - {% elif post['clear_type'] == 5 %}Hard Clear - {% elif post['clear_type'] == 1 %}Normal Clear - {% elif post['clear_type'] == 4 %}Easy Clear - {% else%}Track Lost - {% endif %} - - {% if post['best_clear_type'] == 3 %}(Pure Memory) - {% elif post['best_clear_type'] == 2 %}(Full Recall) - {% elif post['best_clear_type'] == 5 %}(Hard Clear) - {% elif post['best_clear_type'] == 1 %}(Normal Clear) - {% elif post['best_clear_type'] == 4 %}(Easy Clear) - {% else%}(Track Lost) - {% endif %} - -
-
成绩评价 Rating: {{post['rating']}}
-
日期 Date: - {{post['time_played']}} -
-
- - {% if not loop.last %} -
- {% endif %} - {% endfor %} -
- - {% if recent %} -
Recent 30
- {% for i in recent %} - - {% if i %} -
- - {{i['song_id']}} - - {% if i['difficulty'] == 0 %} - PST - {% elif i['difficulty'] == 1 %} - PRS - {% elif i['difficulty'] == 2 %} - FTR - {% else %} - BYD - {% endif %} - {{loop.index}} -
成绩评价 Rating: {{i['rating']}}
-
- - {% if not loop.last %} -
- {% endif %} - - {% endif %} - {% endfor %} - {% endif %} - {% endif %} -
+{% extends 'base.html' %} +{% block header %} +

{% block title %}Single player ptt{% endblock %}

+{% endblock %} + +{% block content %} +
+ + + or
+ + + +
+
+
+ {% if user %} +
+ +
+
玩家信息 Player information
+
{{user['name']}} + UID: {{user['user_id']}} + User code: {{user['user_code']}} +
+
注册于 Registered in: {{user['join_date']}}
+
PTT: {{user['rating_ptt']//100 ~ '.' ~ user['rating_ptt']%100}}
+
Best 30 PTT: {{bestptt}}
+
Recent 10 PTT: {{recentptt}}
+
+
Recent plays:
+
+
+ + {{user['song_id']}} + + {% if user['difficulty'] == 0 %} + PST + {% elif user['difficulty'] == 1 %} + PRS + {% elif user['difficulty'] == 2 %} + FTR + {% else %} + BYD + {% endif %} + +
+
+ + + + + + + + + + + + + + + + + + +
PURE: {{user['perfect_count']}} {{'(' ~ user['shiny_perfect_count'] ~ ')'}}
FAR: {{user['near_count']}}
LOST: {{user['miss_count']}}
+
+
{{user['score']}}
+
+ {% if user['clear_type'] == 3 %}Pure Memory + {% elif user['clear_type'] == 2 %}Full Recall + {% elif user['clear_type'] == 5 %}Hard Clear + {% elif user['clear_type'] == 1 %}Normal Clear + {% elif user['clear_type'] == 4 %}Easy Clear + {% else%}Track Lost + {% endif %} +
+
成绩评价 Rating: {{user['rating']}}
+
日期 Date: + {{user['time_played']}} +
+
+
+
+
+
+ {% if posts %} +
Best 30
+ {% endif %} + {% for post in posts %} +
+ + {{post['song_id']}} + + {% if post['difficulty'] == 0 %} + PST + {% elif post['difficulty'] == 1 %} + PRS + {% elif post['difficulty'] == 2 %} + FTR + {% else %} + BYD + {% endif %} + {{'#' ~ post['rank']}} + +
+
+ + + + + + + + + + + + + + + + + + +
PURE: {{post['perfect_count']}} {{'(' ~ post['shiny_perfect_count'] ~ ')'}}
FAR: {{post['near_count']}}
LOST: {{post['miss_count']}}
+
+
{{post['score']}}
+
+ {% if post['clear_type'] == 3 %}Pure Memory + {% elif post['clear_type'] == 2 %}Full Recall + {% elif post['clear_type'] == 5 %}Hard Clear + {% elif post['clear_type'] == 1 %}Normal Clear + {% elif post['clear_type'] == 4 %}Easy Clear + {% else%}Track Lost + {% endif %} + + {% if post['best_clear_type'] == 3 %}(Pure Memory) + {% elif post['best_clear_type'] == 2 %}(Full Recall) + {% elif post['best_clear_type'] == 5 %}(Hard Clear) + {% elif post['best_clear_type'] == 1 %}(Normal Clear) + {% elif post['best_clear_type'] == 4 %}(Easy Clear) + {% else%}(Track Lost) + {% endif %} + +
+
成绩评价 Rating: {{post['rating']}}
+
日期 Date: + {{post['time_played']}} +
+
+ + {% if not loop.last %} +
+ {% endif %} + {% endfor %} +
+ + {% if recent %} +
Recent 30
+ {% for i in recent %} + + {% if i %} +
+ + {{i['song_id']}} + + {% if i['difficulty'] == 0 %} + PST + {% elif i['difficulty'] == 1 %} + PRS + {% elif i['difficulty'] == 2 %} + FTR + {% else %} + BYD + {% endif %} + {{loop.index}} +
成绩评价 Rating: {{i['rating']}}
+
+ + {% if not loop.last %} +
+ {% endif %} + + {% endif %} + {% endfor %} + {% endif %} + {% endif %} +
{% endblock %} \ No newline at end of file diff --git a/v1.3/templates/web/updatedatabase.html b/latest version/templates/web/updatedatabase.html similarity index 97% rename from v1.3/templates/web/updatedatabase.html rename to latest version/templates/web/updatedatabase.html index ea47675..211e1b5 100644 --- a/v1.3/templates/web/updatedatabase.html +++ b/latest version/templates/web/updatedatabase.html @@ -1,21 +1,21 @@ -{% extends 'base.html' %} -{% block header %} -

{% block title %}Update databases{% endblock %}

-{% endblock %} - -{% block content %} -
- - - -
-
- 这里可以将旧版本的数据库同步到新版本的数据库,并刷新用户拥有的角色列表。
- 可上传文件: arcaea_database.db和arcsong.db
- 新数据库不存在的数据会被添加,存在的数据将不会被改变。

- Here you can synchronize the old version of the database to the new version of the database and refresh the list of - characters owned by players.
- Uploadable files: arcaea_database.db & arcsong.db
- Data that does not exist in the new database will be added and the existing data will not be changed. -
+{% extends 'base.html' %} +{% block header %} +

{% block title %}Update databases{% endblock %}

+{% endblock %} + +{% block content %} +
+ + + +
+
+ 这里可以将旧版本的数据库同步到新版本的数据库,并刷新用户拥有的角色列表。
+ 可上传文件: arcaea_database.db和arcsong.db
+ 新数据库不存在的数据会被添加,存在的数据将不会被改变。

+ Here you can synchronize the old version of the database to the new version of the database and refresh the list of + characters owned by players.
+ Uploadable files: arcaea_database.db & arcsong.db
+ Data that does not exist in the new database will be added and the existing data will not be changed. +
{% endblock %} \ No newline at end of file diff --git a/v1.3/web/index.py b/latest version/web/index.py similarity index 96% rename from v1.3/web/index.py rename to latest version/web/index.py index b63a2d6..2feaafe 100644 --- a/v1.3/web/index.py +++ b/latest version/web/index.py @@ -1,360 +1,360 @@ -from flask import ( - Blueprint, flash, g, redirect, render_template, request, url_for -) -from web.login import login_required -from werkzeug.utils import secure_filename -import sqlite3 -import web.webscore -import web.system -import time -import server.arcscore -import os - -UPLOAD_FOLDER = 'database' -ALLOWED_EXTENSIONS = {'db'} - -bp = Blueprint('index', __name__, url_prefix='/web') - - -def is_number(s): - try: # 判断字符串s是浮点数 - float(s) - return True - except ValueError: - pass - return False - - -@bp.route('/index') -@bp.route('/') -@login_required -def index(): - # 主页 - return render_template('web/index.html') - - -@bp.route('/singleplayer', methods=['POST', 'GET']) -@login_required -def single_player_score(): - # 单个玩家分数查询 - if request.method == 'POST': - name = request.form['name'] - user_code = request.form['user_code'] - error = None - if name or user_code: - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - if user_code: - c.execute('''select user_id from user where user_code=:a''', { - 'a': user_code}) - else: - c.execute( - '''select user_id from user where name=:a''', {'a': name}) - - user_id = c.fetchone() - posts = [] - if user_id: - user_id = user_id[0] - posts = web.webscore.get_user_score(c, user_id) - if not posts: - error = '无成绩 No score.' - else: - error = '玩家不存在 The player does not exist.' - conn.commit() - conn.close() - - else: - error = '输入为空 Null Input.' - - if error: - flash(error) - else: - return render_template('web/singleplayer.html', posts=posts) - - return render_template('web/singleplayer.html') - - -@bp.route('/singleplayerptt', methods=['POST', 'GET']) -@login_required -def single_player_ptt(): - # 单个玩家PTT详情查询 - if request.method == 'POST': - name = request.form['name'] - user_code = request.form['user_code'] - error = None - if name or user_code: - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - if user_code: - c.execute('''select user_id from user where user_code=:a''', { - 'a': user_code}) - else: - c.execute( - '''select user_id from user where name=:a''', {'a': name}) - - user_id = c.fetchone() - posts = [] - if user_id: - user_id = user_id[0] - user = web.webscore.get_user(c, user_id) - posts = web.webscore.get_user_score(c, user_id, 30) - recent, recentptt = web.webscore.get_user_recent30(c, user_id) - if not posts: - error = '无成绩 No score.' - else: - bestptt = 0 - for i in posts: - if i['rating']: - bestptt += i['rating'] - bestptt = bestptt / 30 - else: - error = '玩家不存在 The player does not exist.' - - conn.commit() - conn.close() - else: - error = '输入为空 Null Input.' - - if error: - flash(error) - else: - return render_template('web/singleplayerptt.html', posts=posts, user=user, recent=recent, recentptt=recentptt, bestptt=bestptt) - - return render_template('web/singleplayerptt.html') - - -@bp.route('/allplayer', methods=['GET']) -@login_required -def all_player(): - # 所有玩家数据,按照ptt排序 - conn = sqlite3.connect('./database/arcaea_database.db') - c = conn.cursor() - c.execute('''select * from user order by rating_ptt DESC''') - x = c.fetchall() - error = None - if x: - posts = [] - for i in x: - join_data = None - time_played = None - if i[3]: - join_date = time.strftime('%Y-%m-%d %H:%M:%S', - time.localtime(int(i[3])//1000)) - if i[20]: - time_played = time.strftime('%Y-%m-%d %H:%M:%S', - time.localtime(int(i[20])//1000)) - posts.append({'name': i[1], - 'user_id': i[0], - 'join_date': join_date, - 'user_code': i[4], - 'rating_ptt': i[5], - 'song_id': i[11], - 'difficulty': i[12], - 'score': i[13], - 'shiny_perfect_count': i[14], - 'perfect_count': i[15], - 'near_count': i[16], - 'miss_count': i[17], - 'time_played': time_played, - 'clear_type': i[21], - 'rating': i[22] - }) - else: - error = '没有玩家数据 No player data.' - - conn.commit() - conn.close() - if error: - flash(error) - return render_template('web/allplayer.html') - else: - return render_template('web/allplayer.html', posts=posts) - - -@bp.route('/allsong', methods=['GET']) -@login_required -def all_song(): - # 所有歌曲数据 - def defnum(x): - # 定数转换 - if x >= 0: - return x / 10 - else: - return None - - conn = sqlite3.connect('./database/arcsong.db') - c = conn.cursor() - c.execute('''select * from songs''') - x = c.fetchall() - error = None - if x: - posts = [] - for i in x: - posts.append({'song_id': i[0], - 'name_en': i[1], - 'rating_pst': defnum(i[12]), - 'rating_prs': defnum(i[13]), - 'rating_ftr': defnum(i[14]), - 'rating_byn': defnum(i[15]) - }) - else: - error = '没有铺面数据 No song data.' - - conn.commit() - conn.close() - if error: - flash(error) - return render_template('web/allsong.html') - else: - return render_template('web/allsong.html', posts=posts) - - -@bp.route('/singlecharttop', methods=['GET', 'POST']) -@login_required -def single_chart_top(): - # 歌曲排行榜 - if request.method == 'POST': - song_name = request.form['sid'] - difficulty = request.form['difficulty'] - if difficulty.isdigit(): - difficulty = int(difficulty) - error = None - conn = sqlite3.connect('./database/arcsong.db') - c = conn.cursor() - song_name = '%'+song_name+'%' - c.execute('''select sid, name_en from songs where sid like :a limit 1''', - {'a': song_name}) - x = c.fetchone() - conn.commit() - conn.close() - print(x) - if x: - song_id = x[0] - posts = server.arcscore.arc_score_top(song_id, difficulty, -1) - for i in posts: - i['time_played'] = time.strftime('%Y-%m-%d %H:%M:%S', - time.localtime(i['time_played'])) - else: - error = '查询为空 No song.' - - if not error: - return render_template('web/singlecharttop.html', posts=posts, song_name_en=x[1], song_id=song_id, difficulty=difficulty) - else: - flash(error) - - return render_template('web/singlecharttop.html') - - -def allowed_file(filename): - return '.' in filename and \ - filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS - - -@bp.route('/updatedatabase', methods=['GET', 'POST']) -@login_required -def update_database(): - # 更新数据库 - error = None - if request.method == 'POST': - if 'file' not in request.files: - flash('无文件 No file part.') - return redirect(request.url) - file = request.files['file'] - if file.filename == '': - flash('未选择文件 No selected file.') - return redirect(request.url) - - if file and allowed_file(file.filename): - filename = 'old_' + secure_filename(file.filename) - file.save(os.path.join(UPLOAD_FOLDER, filename)) - flash('上传成功 Success upload.') - try: - web.system.update_database() - flash('数据更新成功 Success update data.') - except: - flash('数据更新失败 Cannot update data.') - else: - error = '上传失败 Upload error.' - - if error: - flash(error) - - return render_template('web/updatedatabase.html') - - -@bp.route('/changesong', methods=['GET']) -@login_required -def change_song(): - # 修改歌曲数据 - return render_template('web/changesong.html') - - -@bp.route('/changesong/addsong', methods=['POST']) -@login_required -def add_song(): - # 添加歌曲数据 - def get_rating(x): - # 换算定数 - if is_number(x): - x = float(x) - if x >= 0: - return int(x*10) - else: - return -1 - else: - return -1 - - error = None - song_id = request.form['sid'] - name_en = request.form['name_en'] - rating_pst = get_rating(request.form['rating_pst']) - rating_prs = get_rating(request.form['rating_prs']) - rating_ftr = get_rating(request.form['rating_ftr']) - rating_byd = get_rating(request.form['rating_byd']) - if len(song_id) >= 256: - song_id = song_id[:200] - if len(name_en) >= 256: - name_en = name_en[:200] - conn = sqlite3.connect('./database/arcsong.db') - c = conn.cursor() - c.execute( - '''select exists(select * from songs where sid=:a)''', {'a': song_id}) - if c.fetchone() == (0,): - c.execute('''insert into songs(sid,name_en,rating_pst,rating_prs,rating_ftr,rating_byn) values(:a,:b,:c,:d,:e,:f)''', { - 'a': song_id, 'b': name_en, 'c': rating_pst, 'd': rating_prs, 'e': rating_ftr, 'f': rating_byd}) - flash('歌曲添加成功 Successfully add the song.') - else: - error = '歌曲已存在 The song exists.' - - conn.commit() - conn.close() - - if error: - flash(error) - - return redirect(url_for('index.change_song')) - - -@bp.route('/changesong/deletesong', methods=['POST']) -@login_required -def delete_song(): - # 删除歌曲数据 - - error = None - song_id = request.form['sid'] - conn = sqlite3.connect('./database/arcsong.db') - c = conn.cursor() - c.execute( - '''select exists(select * from songs where sid=:a)''', {'a': song_id}) - if c.fetchone() == (1,): - c.execute('''delete from songs where sid=:a''', {'a': song_id}) - flash('歌曲删除成功 Successfully delete the song.') - else: - error = "歌曲不存在 The song doesn't exist." - - conn.commit() - conn.close() - if error: - flash(error) - - return redirect(url_for('index.change_song')) +from flask import ( + Blueprint, flash, g, redirect, render_template, request, url_for +) +from web.login import login_required +from werkzeug.utils import secure_filename +import sqlite3 +import web.webscore +import web.system +import time +import server.arcscore +import os + +UPLOAD_FOLDER = 'database' +ALLOWED_EXTENSIONS = {'db'} + +bp = Blueprint('index', __name__, url_prefix='/web') + + +def is_number(s): + try: # 判断字符串s是浮点数 + float(s) + return True + except ValueError: + pass + return False + + +@bp.route('/index') +@bp.route('/') +@login_required +def index(): + # 主页 + return render_template('web/index.html') + + +@bp.route('/singleplayer', methods=['POST', 'GET']) +@login_required +def single_player_score(): + # 单个玩家分数查询 + if request.method == 'POST': + name = request.form['name'] + user_code = request.form['user_code'] + error = None + if name or user_code: + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + if user_code: + c.execute('''select user_id from user where user_code=:a''', { + 'a': user_code}) + else: + c.execute( + '''select user_id from user where name=:a''', {'a': name}) + + user_id = c.fetchone() + posts = [] + if user_id: + user_id = user_id[0] + posts = web.webscore.get_user_score(c, user_id) + if not posts: + error = '无成绩 No score.' + else: + error = '玩家不存在 The player does not exist.' + conn.commit() + conn.close() + + else: + error = '输入为空 Null Input.' + + if error: + flash(error) + else: + return render_template('web/singleplayer.html', posts=posts) + + return render_template('web/singleplayer.html') + + +@bp.route('/singleplayerptt', methods=['POST', 'GET']) +@login_required +def single_player_ptt(): + # 单个玩家PTT详情查询 + if request.method == 'POST': + name = request.form['name'] + user_code = request.form['user_code'] + error = None + if name or user_code: + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + if user_code: + c.execute('''select user_id from user where user_code=:a''', { + 'a': user_code}) + else: + c.execute( + '''select user_id from user where name=:a''', {'a': name}) + + user_id = c.fetchone() + posts = [] + if user_id: + user_id = user_id[0] + user = web.webscore.get_user(c, user_id) + posts = web.webscore.get_user_score(c, user_id, 30) + recent, recentptt = web.webscore.get_user_recent30(c, user_id) + if not posts: + error = '无成绩 No score.' + else: + bestptt = 0 + for i in posts: + if i['rating']: + bestptt += i['rating'] + bestptt = bestptt / 30 + else: + error = '玩家不存在 The player does not exist.' + + conn.commit() + conn.close() + else: + error = '输入为空 Null Input.' + + if error: + flash(error) + else: + return render_template('web/singleplayerptt.html', posts=posts, user=user, recent=recent, recentptt=recentptt, bestptt=bestptt) + + return render_template('web/singleplayerptt.html') + + +@bp.route('/allplayer', methods=['GET']) +@login_required +def all_player(): + # 所有玩家数据,按照ptt排序 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select * from user order by rating_ptt DESC''') + x = c.fetchall() + error = None + if x: + posts = [] + for i in x: + join_data = None + time_played = None + if i[3]: + join_date = time.strftime('%Y-%m-%d %H:%M:%S', + time.localtime(int(i[3])//1000)) + if i[20]: + time_played = time.strftime('%Y-%m-%d %H:%M:%S', + time.localtime(int(i[20])//1000)) + posts.append({'name': i[1], + 'user_id': i[0], + 'join_date': join_date, + 'user_code': i[4], + 'rating_ptt': i[5], + 'song_id': i[11], + 'difficulty': i[12], + 'score': i[13], + 'shiny_perfect_count': i[14], + 'perfect_count': i[15], + 'near_count': i[16], + 'miss_count': i[17], + 'time_played': time_played, + 'clear_type': i[21], + 'rating': i[22] + }) + else: + error = '没有玩家数据 No player data.' + + conn.commit() + conn.close() + if error: + flash(error) + return render_template('web/allplayer.html') + else: + return render_template('web/allplayer.html', posts=posts) + + +@bp.route('/allsong', methods=['GET']) +@login_required +def all_song(): + # 所有歌曲数据 + def defnum(x): + # 定数转换 + if x >= 0: + return x / 10 + else: + return None + + conn = sqlite3.connect('./database/arcsong.db') + c = conn.cursor() + c.execute('''select * from songs''') + x = c.fetchall() + error = None + if x: + posts = [] + for i in x: + posts.append({'song_id': i[0], + 'name_en': i[1], + 'rating_pst': defnum(i[12]), + 'rating_prs': defnum(i[13]), + 'rating_ftr': defnum(i[14]), + 'rating_byn': defnum(i[15]) + }) + else: + error = '没有铺面数据 No song data.' + + conn.commit() + conn.close() + if error: + flash(error) + return render_template('web/allsong.html') + else: + return render_template('web/allsong.html', posts=posts) + + +@bp.route('/singlecharttop', methods=['GET', 'POST']) +@login_required +def single_chart_top(): + # 歌曲排行榜 + if request.method == 'POST': + song_name = request.form['sid'] + difficulty = request.form['difficulty'] + if difficulty.isdigit(): + difficulty = int(difficulty) + error = None + conn = sqlite3.connect('./database/arcsong.db') + c = conn.cursor() + song_name = '%'+song_name+'%' + c.execute('''select sid, name_en from songs where sid like :a limit 1''', + {'a': song_name}) + x = c.fetchone() + conn.commit() + conn.close() + print(x) + if x: + song_id = x[0] + posts = server.arcscore.arc_score_top(song_id, difficulty, -1) + for i in posts: + i['time_played'] = time.strftime('%Y-%m-%d %H:%M:%S', + time.localtime(i['time_played'])) + else: + error = '查询为空 No song.' + + if not error: + return render_template('web/singlecharttop.html', posts=posts, song_name_en=x[1], song_id=song_id, difficulty=difficulty) + else: + flash(error) + + return render_template('web/singlecharttop.html') + + +def allowed_file(filename): + return '.' in filename and \ + filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS + + +@bp.route('/updatedatabase', methods=['GET', 'POST']) +@login_required +def update_database(): + # 更新数据库 + error = None + if request.method == 'POST': + if 'file' not in request.files: + flash('无文件 No file part.') + return redirect(request.url) + file = request.files['file'] + if file.filename == '': + flash('未选择文件 No selected file.') + return redirect(request.url) + + if file and allowed_file(file.filename) and file.filename in ['arcsong.db', 'arcaea_database.db']: + filename = 'old_' + secure_filename(file.filename) + file.save(os.path.join(UPLOAD_FOLDER, filename)) + flash('上传成功 Success upload.') + try: + web.system.update_database() + flash('数据更新成功 Success update data.') + except: + flash('数据更新失败 Cannot update data.') + else: + error = '上传失败 Upload error.' + + if error: + flash(error) + + return render_template('web/updatedatabase.html') + + +@bp.route('/changesong', methods=['GET']) +@login_required +def change_song(): + # 修改歌曲数据 + return render_template('web/changesong.html') + + +@bp.route('/changesong/addsong', methods=['POST']) +@login_required +def add_song(): + # 添加歌曲数据 + def get_rating(x): + # 换算定数 + if is_number(x): + x = float(x) + if x >= 0: + return int(x*10) + else: + return -1 + else: + return -1 + + error = None + song_id = request.form['sid'] + name_en = request.form['name_en'] + rating_pst = get_rating(request.form['rating_pst']) + rating_prs = get_rating(request.form['rating_prs']) + rating_ftr = get_rating(request.form['rating_ftr']) + rating_byd = get_rating(request.form['rating_byd']) + if len(song_id) >= 256: + song_id = song_id[:200] + if len(name_en) >= 256: + name_en = name_en[:200] + conn = sqlite3.connect('./database/arcsong.db') + c = conn.cursor() + c.execute( + '''select exists(select * from songs where sid=:a)''', {'a': song_id}) + if c.fetchone() == (0,): + c.execute('''insert into songs(sid,name_en,rating_pst,rating_prs,rating_ftr,rating_byn) values(:a,:b,:c,:d,:e,:f)''', { + 'a': song_id, 'b': name_en, 'c': rating_pst, 'd': rating_prs, 'e': rating_ftr, 'f': rating_byd}) + flash('歌曲添加成功 Successfully add the song.') + else: + error = '歌曲已存在 The song exists.' + + conn.commit() + conn.close() + + if error: + flash(error) + + return redirect(url_for('index.change_song')) + + +@bp.route('/changesong/deletesong', methods=['POST']) +@login_required +def delete_song(): + # 删除歌曲数据 + + error = None + song_id = request.form['sid'] + conn = sqlite3.connect('./database/arcsong.db') + c = conn.cursor() + c.execute( + '''select exists(select * from songs where sid=:a)''', {'a': song_id}) + if c.fetchone() == (1,): + c.execute('''delete from songs where sid=:a''', {'a': song_id}) + flash('歌曲删除成功 Successfully delete the song.') + else: + error = "歌曲不存在 The song doesn't exist." + + conn.commit() + conn.close() + if error: + flash(error) + + return redirect(url_for('index.change_song')) diff --git a/v1.3/web/login.py b/latest version/web/login.py similarity index 96% rename from v1.3/web/login.py rename to latest version/web/login.py index 5c8e007..5077a6a 100644 --- a/v1.3/web/login.py +++ b/latest version/web/login.py @@ -1,50 +1,50 @@ -#import sqlite3 -from flask import (Blueprint, flash, g, redirect, - render_template, request, session, url_for) -import functools - -bp = Blueprint('login', __name__, url_prefix='/web') - - -@bp.route('/login', methods=('GET', 'POST')) -def login(): - # 登录 - if request.method == 'POST': - username = request.form['username'] - password = request.form['password'] - error = None - - if username != 'admin' and password != 'admin': - error = '错误的用户名或密码 Incorrect username or password.' - - if error is None: - session.clear() - session['user_id'] = 'admin' - return redirect(url_for('index.index')) - - flash(error) - - return render_template('web/login.html') - - -@bp.route('/logout') -def logout(): - # 登出 - session.clear() - flash('成功登出 Successfully log out.') - return redirect(url_for('index.index')) - - -def login_required(view): - # 登录验证,写成了修饰器 - @functools.wraps(view) - def wrapped_view(**kwargs): - x = session.get('user_id') - # 少用户存在验证 - if x is None: - return redirect(url_for('login.login')) - - g.user = {'user_id': x, 'username': 'admin'} - return view(**kwargs) - - return wrapped_view +#import sqlite3 +from flask import (Blueprint, flash, g, redirect, + render_template, request, session, url_for) +import functools + +bp = Blueprint('login', __name__, url_prefix='/web') + + +@bp.route('/login', methods=('GET', 'POST')) +def login(): + # 登录 + if request.method == 'POST': + username = request.form['username'] + password = request.form['password'] + error = None + + if username != 'admin' and password != 'admin': + error = '错误的用户名或密码 Incorrect username or password.' + + if error is None: + session.clear() + session['user_id'] = 'admin' + return redirect(url_for('index.index')) + + flash(error) + + return render_template('web/login.html') + + +@bp.route('/logout') +def logout(): + # 登出 + session.clear() + flash('成功登出 Successfully log out.') + return redirect(url_for('index.index')) + + +def login_required(view): + # 登录验证,写成了修饰器 + @functools.wraps(view) + def wrapped_view(**kwargs): + x = session.get('user_id') + # 少用户存在验证 + if x is None: + return redirect(url_for('login.login')) + + g.user = {'user_id': x, 'username': 'admin'} + return view(**kwargs) + + return wrapped_view diff --git a/v1.3/web/system.py b/latest version/web/system.py similarity index 98% rename from v1.3/web/system.py rename to latest version/web/system.py index c469f24..61d8738 100644 --- a/v1.3/web/system.py +++ b/latest version/web/system.py @@ -1,113 +1,113 @@ -import os -import sqlite3 - - -def update_user_char(c): - # 用character数据更新user_char - c.execute('''select * from character''') - x = c.fetchall() - c.execute('''select user_id from user''') - y = c.fetchall() - if x and y: - for j in y: - for i in x: - c.execute('''delete from user_char where user_id=:a and character_id=:b''', { - 'a': j[0], 'b': i[0]}) - c.execute('''insert into user_char values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o)''', { - 'a': j[0], 'b': i[0], 'c': i[2], 'd': i[3], 'e': i[4], 'f': i[5], 'g': i[6], 'h': i[7], 'i': i[8], 'j': i[9], 'k': i[10], 'l': i[11], 'm': i[12], 'n': i[14], 'o': i[15]}) - - -def update_database(): - # 将old数据库不存在数据加入到新数据库上,并删除old数据库 - # 对于arcaea_datebase.db,更新best_score,friend,recent30,user,user_world并用character数据更新user_char - # 对于arcsong.db,更新songs - if os.path.isfile("database/old_arcaea_database.db") and os.path.isfile("database/arcaea_database.db"): - conn1 = sqlite3.connect('./database/old_arcaea_database.db') - c1 = conn1.cursor() - conn2 = sqlite3.connect('./database/arcaea_database.db') - c2 = conn2.cursor() - - # user - c1.execute('''select * from user''') - x = c1.fetchall() - if x: - for i in x: - c2.execute( - '''select exists(select * from user where user_id=:a)''', {'a': i[0]}) - if c2.fetchone() == (0,): - c2.execute('''insert into user values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25)''', { - 'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25]}) - - # friend - c1.execute('''select * from friend''') - x = c1.fetchall() - if x: - for i in x: - c2.execute( - '''select exists(select * from friend where user_id_me=:a and user_id_other=:b)''', {'a': i[0], 'b': i[1]}) - if c2.fetchone() == (0,): - c2.execute('''insert into friend values(:a,:b)''', { - 'a': i[0], 'b': i[1]}) - - # best_score - c1.execute('''select * from best_score''') - x = c1.fetchall() - if x: - for i in x: - c2.execute('''select exists(select * from best_score where user_id=:a and song_id=:b and difficulty=:c)''', { - 'a': i[0], 'b': i[1], 'c': i[2]}) - if c2.fetchone() == (0,): - c2.execute('''insert into best_score values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13)''', { - 'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13]}) - - # recent30 - c1.execute('''select * from recent30''') - x = c1.fetchall() - if x: - for i in x: - c2.execute( - '''select exists(select * from recent30 where user_id=:a)''', {'a': i[0]}) - if c2.fetchone() == (0,): - c2.execute('''insert into recent30 values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25,:a26,:a27,:a28,:a29,:a30,:a31,:a32,:a33,:a34,:a35,:a36,:a37,:a38,:a39,:a40,:a41,:a42,:a43,:a44,:a45,:a46,:a47,:a48,:a49,:a50,:a51,:a52,:a53,:a54,:a55,:a56,:a57,:a58,:a59,:a60)''', {'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[ - 18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25], 'a26': i[26], 'a27': i[27], 'a28': i[28], 'a29': i[29], 'a30': i[30], 'a31': i[31], 'a32': i[32], 'a33': i[33], 'a34': i[34], 'a35': i[35], 'a36': i[36], 'a37': i[37], 'a38': i[38], 'a39': i[39], 'a40': i[40], 'a41': i[41], 'a42': i[42], 'a43': i[43], 'a44': i[44], 'a45': i[45], 'a46': i[46], 'a47': i[47], 'a48': i[48], 'a49': i[49], 'a50': i[50], 'a51': i[51], 'a52': i[52], 'a53': i[53], 'a54': i[54], 'a55': i[55], 'a56': i[56], 'a57': i[57], 'a58': i[58], 'a59': i[59], 'a60': i[60]}) - - # user_world - c1.execute('''select * from user_world''') - x = c1.fetchall() - if x: - for i in x: - c2.execute( - '''select exists(select * from user_world where user_id=:a and map_id=:b)''', {'a': i[0], 'b': i[1]}) - if c2.fetchone() == (0,): - c2.execute('''insert into user_world values(:a0,:a1,:a2,:a3,:a4)''', { - 'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4]}) - - update_user_char(c2) - conn1.commit() - conn1.close() - conn2.commit() - conn2.close() - os.remove('database/old_arcaea_database.db') - - # songs - if os.path.isfile("database/old_arcsong.db") and os.path.isfile("database/arcsong.db"): - conn1 = sqlite3.connect('./database/old_arcsong.db') - c1 = conn1.cursor() - conn2 = sqlite3.connect('./database/arcsong.db') - c2 = conn2.cursor() - - c1.execute('''select * from songs''') - x = c1.fetchall() - if x: - for i in x: - c2.execute( - '''select exists(select * from songs where sid=:a)''', {'a': i[0]}) - if c2.fetchone() == (0,): - c2.execute('''insert into songs values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25,:a26,:a27)''', {'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[ - 8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25], 'a26': i[26], 'a27': i[27]}) - - conn1.commit() - conn1.close() - conn2.commit() - conn2.close() - os.remove('database/old_arcsong.db') +import os +import sqlite3 + + +def update_user_char(c): + # 用character数据更新user_char + c.execute('''select * from character''') + x = c.fetchall() + c.execute('''select user_id from user''') + y = c.fetchall() + if x and y: + for j in y: + for i in x: + c.execute('''delete from user_char where user_id=:a and character_id=:b''', { + 'a': j[0], 'b': i[0]}) + c.execute('''insert into user_char values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o)''', { + 'a': j[0], 'b': i[0], 'c': i[2], 'd': i[3], 'e': i[4], 'f': i[5], 'g': i[6], 'h': i[7], 'i': i[8], 'j': i[9], 'k': i[10], 'l': i[11], 'm': i[12], 'n': i[14], 'o': i[15]}) + + +def update_database(): + # 将old数据库不存在数据加入到新数据库上,并删除old数据库 + # 对于arcaea_datebase.db,更新best_score,friend,recent30,user,user_world并用character数据更新user_char + # 对于arcsong.db,更新songs + if os.path.isfile("database/old_arcaea_database.db") and os.path.isfile("database/arcaea_database.db"): + conn1 = sqlite3.connect('./database/old_arcaea_database.db') + c1 = conn1.cursor() + conn2 = sqlite3.connect('./database/arcaea_database.db') + c2 = conn2.cursor() + + # user + c1.execute('''select * from user''') + x = c1.fetchall() + if x: + for i in x: + c2.execute( + '''select exists(select * from user where user_id=:a)''', {'a': i[0]}) + if c2.fetchone() == (0,): + c2.execute('''insert into user values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25)''', { + 'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25]}) + + # friend + c1.execute('''select * from friend''') + x = c1.fetchall() + if x: + for i in x: + c2.execute( + '''select exists(select * from friend where user_id_me=:a and user_id_other=:b)''', {'a': i[0], 'b': i[1]}) + if c2.fetchone() == (0,): + c2.execute('''insert into friend values(:a,:b)''', { + 'a': i[0], 'b': i[1]}) + + # best_score + c1.execute('''select * from best_score''') + x = c1.fetchall() + if x: + for i in x: + c2.execute('''select exists(select * from best_score where user_id=:a and song_id=:b and difficulty=:c)''', { + 'a': i[0], 'b': i[1], 'c': i[2]}) + if c2.fetchone() == (0,): + c2.execute('''insert into best_score values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13)''', { + 'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13]}) + + # recent30 + c1.execute('''select * from recent30''') + x = c1.fetchall() + if x: + for i in x: + c2.execute( + '''select exists(select * from recent30 where user_id=:a)''', {'a': i[0]}) + if c2.fetchone() == (0,): + c2.execute('''insert into recent30 values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25,:a26,:a27,:a28,:a29,:a30,:a31,:a32,:a33,:a34,:a35,:a36,:a37,:a38,:a39,:a40,:a41,:a42,:a43,:a44,:a45,:a46,:a47,:a48,:a49,:a50,:a51,:a52,:a53,:a54,:a55,:a56,:a57,:a58,:a59,:a60)''', {'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[ + 18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25], 'a26': i[26], 'a27': i[27], 'a28': i[28], 'a29': i[29], 'a30': i[30], 'a31': i[31], 'a32': i[32], 'a33': i[33], 'a34': i[34], 'a35': i[35], 'a36': i[36], 'a37': i[37], 'a38': i[38], 'a39': i[39], 'a40': i[40], 'a41': i[41], 'a42': i[42], 'a43': i[43], 'a44': i[44], 'a45': i[45], 'a46': i[46], 'a47': i[47], 'a48': i[48], 'a49': i[49], 'a50': i[50], 'a51': i[51], 'a52': i[52], 'a53': i[53], 'a54': i[54], 'a55': i[55], 'a56': i[56], 'a57': i[57], 'a58': i[58], 'a59': i[59], 'a60': i[60]}) + + # user_world + c1.execute('''select * from user_world''') + x = c1.fetchall() + if x: + for i in x: + c2.execute( + '''select exists(select * from user_world where user_id=:a and map_id=:b)''', {'a': i[0], 'b': i[1]}) + if c2.fetchone() == (0,): + c2.execute('''insert into user_world values(:a0,:a1,:a2,:a3,:a4)''', { + 'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4]}) + + update_user_char(c2) + conn1.commit() + conn1.close() + conn2.commit() + conn2.close() + os.remove('database/old_arcaea_database.db') + + # songs + if os.path.isfile("database/old_arcsong.db") and os.path.isfile("database/arcsong.db"): + conn1 = sqlite3.connect('./database/old_arcsong.db') + c1 = conn1.cursor() + conn2 = sqlite3.connect('./database/arcsong.db') + c2 = conn2.cursor() + + c1.execute('''select * from songs''') + x = c1.fetchall() + if x: + for i in x: + c2.execute( + '''select exists(select * from songs where sid=:a)''', {'a': i[0]}) + if c2.fetchone() == (0,): + c2.execute('''insert into songs values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25,:a26,:a27)''', {'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[ + 8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25], 'a26': i[26], 'a27': i[27]}) + + conn1.commit() + conn1.close() + conn2.commit() + conn2.close() + os.remove('database/old_arcsong.db') diff --git a/v1.3/web/webscore.py b/latest version/web/webscore.py similarity index 96% rename from v1.3/web/webscore.py rename to latest version/web/webscore.py index cc99365..08d80ce 100644 --- a/v1.3/web/webscore.py +++ b/latest version/web/webscore.py @@ -1,104 +1,104 @@ -import time - - -def get_user_score(c, user_id, limit=-1): - # 返回用户的所有歌曲数据,带排名,返回字典列表 - if limit >= 0: - c.execute('''select * from best_score where user_id =:a order by rating DESC limit :b''', - {'a': user_id, 'b': limit}) - else: - c.execute( - '''select * from best_score where user_id =:a order by rating DESC''', {'a': user_id}) - x = c.fetchall() - r = [] - if x: - rank = 0 - for i in x: - rank += 1 - r.append({ - "song_id": i[1], - "difficulty": i[2], - "score": i[3], - "shiny_perfect_count": i[4], - "perfect_count": i[5], - "near_count": i[6], - "miss_count": i[7], - "health": i[8], - "modifier": i[9], - "time_played": time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(i[10])), - "best_clear_type": i[11], - "clear_type": i[12], - "rating": i[13], - "rank": rank - }) - - return r - - -def get_user(c, user_id): - # 得到user表部分用户信息,返回字典 - c.execute('''select * from user where user_id = :a''', {'a': user_id}) - x = c.fetchone() - r = None - if x: - join_date = None - time_played = None - if x[3]: - join_date = time.strftime('%Y-%m-%d %H:%M:%S', - time.localtime(int(x[3])//1000)) - if x[20]: - time_played = time.strftime('%Y-%m-%d %H:%M:%S', - time.localtime(int(x[20])//1000)) - - r = {'name': x[1], - 'user_id': user_id, - 'join_date': join_date, - 'user_code': x[4], - 'rating_ptt': x[5], - 'song_id': x[11], - 'difficulty': x[12], - 'score': x[13], - 'shiny_perfect_count': x[14], - 'perfect_count': x[15], - 'near_count': x[16], - 'miss_count': x[17], - 'time_played': time_played, - 'clear_type': x[21], - 'rating': x[22] - } - - return r - - -def get_user_recent30(c, user_id): - # 获取玩家recent30信息并计算这一部分的ptt,返回字典列表和一个值 - c.execute('''select * from recent30 where user_id=:a''', {'a': user_id}) - sumr = 0 - x = c.fetchone() - r = [] - if x is not None: - r30 = [] - s30 = [] - for i in range(1, 61, 2): - if x[i] is not None: - r30.append(float(x[i])) - s30.append(x[i+1]) - else: - r30.append(0) - s30.append('') - r30, s30 = (list(t) for t in zip(*sorted(zip(r30, s30), reverse=True))) - songs = [] - i = 0 - while len(songs) < 10 and i <= 29 and s30[i] != '' and s30[i] is not None: - if s30[i] not in songs: - sumr += r30[i] - songs.append(s30[i]) - i += 1 - for i in range(0, 30): - if s30[i]: - r.append({ - 'song_id': s30[i][:-1], - 'difficulty': int(s30[i][-1]), - 'rating': r30[i] - }) - return r, sumr / 10 +import time + + +def get_user_score(c, user_id, limit=-1): + # 返回用户的所有歌曲数据,带排名,返回字典列表 + if limit >= 0: + c.execute('''select * from best_score where user_id =:a order by rating DESC limit :b''', + {'a': user_id, 'b': limit}) + else: + c.execute( + '''select * from best_score where user_id =:a order by rating DESC''', {'a': user_id}) + x = c.fetchall() + r = [] + if x: + rank = 0 + for i in x: + rank += 1 + r.append({ + "song_id": i[1], + "difficulty": i[2], + "score": i[3], + "shiny_perfect_count": i[4], + "perfect_count": i[5], + "near_count": i[6], + "miss_count": i[7], + "health": i[8], + "modifier": i[9], + "time_played": time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(i[10])), + "best_clear_type": i[11], + "clear_type": i[12], + "rating": i[13], + "rank": rank + }) + + return r + + +def get_user(c, user_id): + # 得到user表部分用户信息,返回字典 + c.execute('''select * from user where user_id = :a''', {'a': user_id}) + x = c.fetchone() + r = None + if x: + join_date = None + time_played = None + if x[3]: + join_date = time.strftime('%Y-%m-%d %H:%M:%S', + time.localtime(int(x[3])//1000)) + if x[20]: + time_played = time.strftime('%Y-%m-%d %H:%M:%S', + time.localtime(int(x[20])//1000)) + + r = {'name': x[1], + 'user_id': user_id, + 'join_date': join_date, + 'user_code': x[4], + 'rating_ptt': x[5], + 'song_id': x[11], + 'difficulty': x[12], + 'score': x[13], + 'shiny_perfect_count': x[14], + 'perfect_count': x[15], + 'near_count': x[16], + 'miss_count': x[17], + 'time_played': time_played, + 'clear_type': x[21], + 'rating': x[22] + } + + return r + + +def get_user_recent30(c, user_id): + # 获取玩家recent30信息并计算这一部分的ptt,返回字典列表和一个值 + c.execute('''select * from recent30 where user_id=:a''', {'a': user_id}) + sumr = 0 + x = c.fetchone() + r = [] + if x is not None: + r30 = [] + s30 = [] + for i in range(1, 61, 2): + if x[i] is not None: + r30.append(float(x[i])) + s30.append(x[i+1]) + else: + r30.append(0) + s30.append('') + r30, s30 = (list(t) for t in zip(*sorted(zip(r30, s30), reverse=True))) + songs = [] + i = 0 + while len(songs) < 10 and i <= 29 and s30[i] != '' and s30[i] is not None: + if s30[i] not in songs: + sumr += r30[i] + songs.append(s30[i]) + i += 1 + for i in range(0, 30): + if s30[i]: + r.append({ + 'song_id': s30[i][:-1], + 'difficulty': int(s30[i][-1]), + 'rating': r30[i] + }) + return r, sumr / 10