feat: Add song difficulty leaderboard feature
This commit is contained in:
135
app.py
135
app.py
@@ -13,6 +13,7 @@ import requests
|
||||
import schema
|
||||
import os
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
# -- カスタム --
|
||||
import traceback
|
||||
@@ -105,6 +106,13 @@ db.users.create_index('username', unique=True)
|
||||
db.songs.create_index('id', unique=True)
|
||||
db.songs.create_index('song_type')
|
||||
db.scores.create_index('username')
|
||||
db.leaderboard.create_index([
|
||||
('song_id', 1),
|
||||
('difficulty', 1),
|
||||
('month', 1),
|
||||
('score', -1)
|
||||
])
|
||||
db.leaderboard.create_index('username')
|
||||
|
||||
|
||||
class HashException(Exception):
|
||||
@@ -746,6 +754,133 @@ def route_api_scores_get():
|
||||
return jsonify({'status': 'ok', 'scores': scores, 'username': user['username'], 'display_name': user['display_name'], 'don': don})
|
||||
|
||||
|
||||
@app.route(basedir + 'api/leaderboard/submit', methods=['POST'])
|
||||
@login_required
|
||||
def route_api_leaderboard_submit():
|
||||
data = request.get_json()
|
||||
if not schema.validate(data, schema.leaderboard_submit):
|
||||
return abort(400)
|
||||
|
||||
username = session.get('username')
|
||||
user = db.users.find_one({'username': username})
|
||||
|
||||
current_month = datetime.now().strftime('%Y-%m')
|
||||
|
||||
# Handle song_id type
|
||||
song_id = data['song_id']
|
||||
|
||||
query = {
|
||||
'song_id': song_id,
|
||||
'difficulty': data['difficulty'],
|
||||
'month': current_month,
|
||||
'username': username
|
||||
}
|
||||
|
||||
existing = db.leaderboard.find_one(query)
|
||||
|
||||
new_record = False
|
||||
rank_info = None
|
||||
|
||||
if not existing or data['score'] > existing['score']:
|
||||
entry = {
|
||||
'song_id': song_id,
|
||||
'difficulty': data['difficulty'],
|
||||
'month': current_month,
|
||||
'username': username,
|
||||
'display_name': user['display_name'],
|
||||
'don': get_db_don(user),
|
||||
'score': data['score'],
|
||||
'good': data.get('good', 0),
|
||||
'ok': data.get('ok', 0),
|
||||
'bad': data.get('bad', 0),
|
||||
'maxCombo': data.get('maxCombo', 0),
|
||||
'timestamp': datetime.now()
|
||||
}
|
||||
db.leaderboard.update_one(query, {'$set': entry}, upsert=True)
|
||||
new_record = True
|
||||
|
||||
# Get rank
|
||||
count = db.leaderboard.count_documents({
|
||||
'song_id': song_id,
|
||||
'difficulty': data['difficulty'],
|
||||
'month': current_month,
|
||||
'score': {'$gt': data['score']}
|
||||
})
|
||||
rank = count + 1
|
||||
rank_info = rank
|
||||
|
||||
return jsonify({
|
||||
'status': 'ok',
|
||||
'new_record': new_record,
|
||||
'rank': rank_info
|
||||
})
|
||||
|
||||
|
||||
@app.route(basedir + 'api/leaderboard/get')
|
||||
def route_api_leaderboard_get():
|
||||
song_id = request.args.get('song_id')
|
||||
difficulty = request.args.get('difficulty')
|
||||
|
||||
if not song_id or not difficulty:
|
||||
return abort(400)
|
||||
|
||||
# Try convert song_id to int if it looks like one
|
||||
if re.match('^[0-9]+$', str(song_id)):
|
||||
song_id = int(song_id)
|
||||
|
||||
current_month = datetime.now().strftime('%Y-%m')
|
||||
|
||||
query = {
|
||||
'song_id': song_id,
|
||||
'difficulty': difficulty,
|
||||
'month': current_month
|
||||
}
|
||||
|
||||
# Get top 50
|
||||
leaderboard = list(db.leaderboard.find(query, {'_id': False}).sort('score', -1).limit(50))
|
||||
|
||||
user_rank = None
|
||||
if session.get('username'):
|
||||
username = session.get('username')
|
||||
user_entry = db.leaderboard.find_one({
|
||||
'song_id': song_id,
|
||||
'difficulty': difficulty,
|
||||
'month': current_month,
|
||||
'username': username
|
||||
}, {'_id': False})
|
||||
|
||||
if user_entry:
|
||||
# Calculate rank
|
||||
count = db.leaderboard.count_documents({
|
||||
'song_id': song_id,
|
||||
'difficulty': difficulty,
|
||||
'month': current_month,
|
||||
'score': {'$gt': user_entry['score']}
|
||||
})
|
||||
user_rank = {
|
||||
'rank': count + 1,
|
||||
'entry': user_entry
|
||||
}
|
||||
|
||||
return jsonify({
|
||||
'status': 'ok',
|
||||
'leaderboard': leaderboard,
|
||||
'user_rank': user_rank
|
||||
})
|
||||
|
||||
|
||||
@app.route(basedir + 'api/leaderboard/reset', methods=['POST'])
|
||||
@admin_required(level=100)
|
||||
def route_api_leaderboard_reset():
|
||||
current_month = datetime.now().strftime('%Y-%m')
|
||||
result = db.leaderboard.delete_many({'month': {'$ne': current_month}})
|
||||
return jsonify({
|
||||
'status': 'ok',
|
||||
'deleted_count': result.deleted_count,
|
||||
'current_month': current_month
|
||||
})
|
||||
|
||||
|
||||
@app.route(basedir + 'privacy')
|
||||
def route_api_privacy():
|
||||
last_modified = time.strftime('%d %B %Y', time.gmtime(os.path.getmtime('templates/privacy.txt')))
|
||||
|
||||
Reference in New Issue
Block a user