import os
import sqlite3
import csv
from flask import Flask, render_template_string, request, redirect, url_for
import pandas as pd # Still needed for initial conversion if not done
from collections import defaultdict
app = Flask(__name__)
# Database file
DB_FILE = 'all_tops.db'
# Function to convert CSV to SQLite if not exists, with indexes for speed
def csv_to_sqlite(csv_file, db_file):
if os.path.exists(db_file):
print(f"Database {db_file} already exists. Skipping conversion.")
return
print(f"Converting {csv_file} to {db_file}...")
conn = sqlite3.connect(db_file)
cur = conn.cursor()
cur.execute('''
CREATE TABLE tops (
stat TEXT,
rank INTEGER,
username TEXT,
uuid TEXT,
raw_value INTEGER,
formatted_value REAL,
unit TEXT
)
''')
with open(csv_file, 'r', encoding='utf-8') as f:
reader = csv.reader(f)
next(reader) # Skip header
cur.executemany('INSERT INTO tops VALUES (?, ?, ?, ?, ?, ?, ?)', reader)
# Add indexes for faster queries
cur.execute('CREATE INDEX idx_username ON tops (username)')
cur.execute('CREATE INDEX idx_uuid ON tops (uuid)')
cur.execute('CREATE INDEX idx_stat ON tops (stat)')
cur.execute('CREATE INDEX idx_rank ON tops (rank)')
cur.execute('CREATE INDEX idx_raw_value ON tops (raw_value)')
conn.commit()
conn.close()
print("Conversion complete with indexes.")
# Run conversion
csv_to_sqlite('all_tops.csv', DB_FILE)
# Connect to DB
def get_db_connection():
conn = sqlite3.connect(DB_FILE)
conn.row_factory = sqlite3.Row
return conn
# Get unique players with pagination
def get_unique_players(page=1, per_page=20):
conn = get_db_connection()
cur = conn.cursor()
offset = (page - 1) * per_page
cur.execute('SELECT COUNT(DISTINCT username) FROM tops')
total = cur.fetchone()[0]
cur.execute('SELECT DISTINCT username FROM tops ORDER BY username LIMIT ? OFFSET ?', (per_page, offset))
players = [row['username'] for row in cur.fetchall()]
conn.close()
return players, total
# Get unique stats
def get_unique_stats():
conn = get_db_connection()
cur = conn.cursor()
cur.execute('SELECT DISTINCT stat FROM tops ORDER BY stat')
stats = [row['stat'] for row in cur.fetchall()]
conn.close()
return stats
# HTML template for main page (no full table to save memory)
main_template = """
Данные о Топах
Данные о Топах из all_tops.db
Всего уникальных игроков: {{ num_players }}
Всего уникальных статистик: {{ num_stats }}
Игроки (Страница {{ page }} из {{ num_pages }})
"""
# HTML template for player page
player_template = """
Игрок: {{ player }}
Игрок: {{ player }}
Назад к Главной
Обзор Лучших Результатов
{% for cat, top_entries in best_groups %}
Лучшее в {{ cat }}
{% for entry in top_entries %}
- {{ entry['stat'] }}: Ранг {{ entry['rank'] }} ({{ entry['formatted_value'] }} {{ entry['unit'] }})
{% endfor %}
{% endfor %}
Все Ранги в Топах
{% for cat, group_entries in sorted_groups %}
{{ cat }}
| Статистика |
Ранг |
Сырое Значение |
Форматированное Значение |
Единица |
{% for entry in group_entries %}
| {{ entry['stat'] }} |
{{ entry['rank'] }} |
{{ entry['raw_value'] }} |
{{ entry['formatted_value'] }} |
{{ entry['unit'] }} |
{% endfor %}
{% endfor %}
"""
@app.route('/')
def index():
page = request.args.get('page', 1, type=int)
per_page = 20
players, total = get_unique_players(page, per_page)
num_pages = (total + per_page - 1) // per_page
return render_template_string(main_template, num_players=total, num_stats=len(get_unique_stats()), players=players, page=page, num_pages=num_pages)
@app.route('/search')
def search():
query = request.args.get('query', '').strip()
if not query:
return redirect(url_for('index'))
conn = get_db_connection()
cur = conn.cursor()
# Check if query is username
cur.execute('SELECT DISTINCT username FROM tops WHERE username = ?', (query,))
result = cur.fetchone()
if result:
conn.close()
return redirect(url_for('player_page', player=query))
# Check if query is uuid
cur.execute('SELECT DISTINCT username FROM tops WHERE uuid = ?', (query,))
result = cur.fetchone()
if result:
conn.close()
return redirect(url_for('player_page', player=result['username']))
conn.close()
return f"Игрок с ником или UUID '{query}' не найден."
@app.route('/player/')
def player_page(player):
conn = get_db_connection()
cur = conn.cursor()
cur.execute('SELECT * FROM tops WHERE username = ? AND raw_value > 0 ORDER BY rank ASC', (player,))
entries = cur.fetchall()
conn.close()
if not entries:
return f"Нет данных для игрока {player}"
uuid = entries[0]['uuid']
grouped = defaultdict(list)
for entry in entries:
stat = entry['stat']
cat = stat.split(':')[0] if ':' in stat else stat
grouped[cat].append(entry)
# Sort groups by the min rank in the group (best performance first)
sorted_groups = sorted(grouped.items(), key=lambda x: min(e['rank'] for e in x[1]))
# For each group, sort entries by rank ASC (best on top)
for cat, group_entries in sorted_groups:
group_entries.sort(key=lambda e: e['rank'])
# For best overview: for each cat, take top 5 best (lowest rank)
best_groups = []
for cat, group_entries in sorted_groups:
top5 = sorted(group_entries, key=lambda e: e['rank'])[:5]
best_groups.append((cat, top5))
return render_template_string(player_template, player=player, sorted_groups=sorted_groups, best_groups=best_groups, uuid=uuid)
if __name__ == '__main__':
print("Starting Flask server...")
app.run(debug=True)