147 lines
5.0 KiB
Python
147 lines
5.0 KiB
Python
![]() |
import os
|
||
|
import glob
|
||
|
from flask import render_template, Blueprint, current_app, request
|
||
|
|
||
|
from app.tasks import get_redis
|
||
|
|
||
|
from app.forms import ScrapingForm
|
||
|
from app.util import get_size
|
||
|
from app.config import load_config
|
||
|
from app.api import scraper as scraper
|
||
|
|
||
|
from app.analysis import load_data, load_analysis_modules
|
||
|
|
||
|
from datetime import datetime
|
||
|
|
||
|
views_bp = Blueprint("views", __name__)
|
||
|
|
||
|
def sizeof_fmt(num, suffix="B"):
|
||
|
"""Convert bytes to human readable format"""
|
||
|
for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]:
|
||
|
if abs(num) < 1024.0:
|
||
|
return f"{num:3.1f} {unit}{suffix}"
|
||
|
num /= 1024.0
|
||
|
return f"{num:.1f} Yi{suffix}"
|
||
|
|
||
|
def register_views(app):
|
||
|
@app.route('/')
|
||
|
def index():
|
||
|
form = ScrapingForm()
|
||
|
return render_template('index.html', form=form)
|
||
|
|
||
|
@app.route('/results')
|
||
|
def results():
|
||
|
return render_template('results.html')
|
||
|
|
||
|
@app.route('/log_viewer')
|
||
|
def log_viewer():
|
||
|
return render_template('log_viewer.html')
|
||
|
|
||
|
@app.route('/download_results')
|
||
|
def download_results():
|
||
|
# Get the current active log file and data file from Redis and app config
|
||
|
redis_client = get_redis()
|
||
|
current_faction_id = redis_client.get("current_faction_id")
|
||
|
|
||
|
active_data_file = None
|
||
|
if current_faction_id:
|
||
|
active_data_file = redis_client.hget(f"scraper:{current_faction_id}", "data_file_name")
|
||
|
|
||
|
active_log_file = app.config['LOG_FILE_NAME']
|
||
|
|
||
|
def get_file_info(file_path, file_type='data'):
|
||
|
stats = os.stat(file_path)
|
||
|
name = os.path.basename(file_path)
|
||
|
|
||
|
# Determine if file is active
|
||
|
is_active = False
|
||
|
if file_type == 'data' and active_data_file:
|
||
|
is_active = os.path.abspath(file_path) == os.path.abspath(active_data_file)
|
||
|
elif file_type == 'log' and active_log_file:
|
||
|
is_active = os.path.basename(file_path) == os.path.basename(active_log_file)
|
||
|
|
||
|
return {
|
||
|
'name': file_path, # Full path for internal use
|
||
|
'name_display': name, # Just filename for display
|
||
|
'last_modified': stats.st_mtime, # Send timestamp instead of datetime
|
||
|
'created': stats.st_ctime, # Send timestamp instead of datetime
|
||
|
'size': sizeof_fmt(stats.st_size),
|
||
|
'active': is_active
|
||
|
}
|
||
|
|
||
|
data_files = []
|
||
|
log_files = []
|
||
|
|
||
|
# Get data files
|
||
|
data_dir = os.path.abspath(app.config['DATA']['DATA_DIR'])
|
||
|
if os.path.exists(data_dir):
|
||
|
for file in glob.glob(os.path.join(data_dir, "*.csv")):
|
||
|
data_files.append(get_file_info(file, 'data'))
|
||
|
|
||
|
# Get log files
|
||
|
log_dir = os.path.abspath(app.config['LOGGING']['LOG_DIR'])
|
||
|
if os.path.exists(log_dir):
|
||
|
for file in glob.glob(os.path.join(log_dir, "*.log")):
|
||
|
log_files.append(get_file_info(file, 'log'))
|
||
|
|
||
|
# Sort files by modification time, newest first
|
||
|
data_files.sort(key=lambda x: x['last_modified'], reverse=True)
|
||
|
log_files.sort(key=lambda x: x['last_modified'], reverse=True)
|
||
|
|
||
|
files = {
|
||
|
'data': data_files,
|
||
|
'log': log_files
|
||
|
}
|
||
|
|
||
|
return render_template('download_results.html', files=files)
|
||
|
|
||
|
views_bp = Blueprint("views", __name__)
|
||
|
|
||
|
@views_bp.route("/analyze", methods=["GET", "POST"])
|
||
|
def analyze():
|
||
|
analysis_modules = load_analysis_modules() # Load available analyses
|
||
|
data_dir = current_app.config.get("DATA", {}).get("DATA_DIR")
|
||
|
|
||
|
selected_file = None
|
||
|
selected_analyses = []
|
||
|
|
||
|
# Find all available CSV files
|
||
|
data_files = sorted(
|
||
|
glob.glob(os.path.join(data_dir, "*.csv")),
|
||
|
key=os.path.getmtime,
|
||
|
reverse=True
|
||
|
) if data_dir else []
|
||
|
|
||
|
context = {
|
||
|
"data_files": data_files,
|
||
|
"analyses": analysis_modules,
|
||
|
"selected_file": selected_file,
|
||
|
"selected_analyses": selected_analyses
|
||
|
}
|
||
|
|
||
|
if request.method == "POST":
|
||
|
selected_analyses = request.form.getlist("analyses")
|
||
|
selected_file = request.form.get("data_file")
|
||
|
|
||
|
if not selected_file:
|
||
|
context["error"] = "No file selected."
|
||
|
return render_template("analyze.html", **context)
|
||
|
|
||
|
df = load_data(selected_file)
|
||
|
results = {}
|
||
|
|
||
|
for analysis in analysis_modules:
|
||
|
if analysis.name in selected_analyses:
|
||
|
results[analysis.name] = analysis.execute(df) # Some may return HTML
|
||
|
|
||
|
context["results"] = results
|
||
|
|
||
|
return render_template("analyze.html", **context)
|
||
|
|
||
|
@views_bp.route('/server_time')
|
||
|
def server_time():
|
||
|
current_time = datetime.now(datetime.timezone.utc).strftime('%Y-%m-%d %H:%M:%S')
|
||
|
return {'server_time': current_time}
|
||
|
|
||
|
app.register_blueprint(views_bp)
|