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 }}

{% endfor %}

Все Ранги в Топах

{% for cat, group_entries in sorted_groups %}

{{ cat }}

{% for entry in group_entries %} {% endfor %}
Статистика Ранг Сырое Значение Форматированное Значение Единица
{{ entry['stat'] }} {{ entry['rank'] }} {{ entry['raw_value'] }} {{ entry['formatted_value'] }} {{ entry['unit'] }}
{% 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)