90 lines
3.4 KiB
Python
90 lines
3.4 KiB
Python
from flask import Flask, render_template, request, redirect, url_for
|
|
from models import db, Problem, Solution
|
|
from utils import run_code_against_tests
|
|
from leaderboard import create_leaderboard_table, log_leaderboard, get_leaderboard
|
|
|
|
|
|
import os
|
|
from problem_loader import load_problems_from_json, schedule_problem_reload
|
|
|
|
app = Flask(__name__)
|
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite3'
|
|
db.init_app(app)
|
|
|
|
|
|
|
|
@app.before_request
|
|
def setup():
|
|
db.create_all()
|
|
create_leaderboard_table() # Ensure leaderboard table exists
|
|
# Load problems from JSON at startup
|
|
json_path = os.path.join(os.path.dirname(__file__), 'problems.json')
|
|
load_problems_from_json(json_path)
|
|
# Schedule reload every 10 hours
|
|
schedule_problem_reload(app, json_path, interval_hours=10)
|
|
|
|
@app.route('/')
|
|
def index():
|
|
problems = Problem.query.all()
|
|
leaderboard = get_leaderboard()
|
|
# Map problem_id to title for leaderboard display
|
|
problem_titles = {p.id: p.title for p in problems}
|
|
return render_template('index.html', problems=problems, leaderboard=leaderboard, problem_titles=problem_titles)
|
|
|
|
@app.route('/problem/new', methods=['GET', 'POST'])
|
|
def new_problem():
|
|
if request.method == 'POST':
|
|
title = request.form['title']
|
|
description = request.form['description']
|
|
test_code = request.form['test_code']
|
|
problem = Problem(title=title, description=description, test_code=test_code)
|
|
db.session.add(problem)
|
|
db.session.commit()
|
|
return redirect(url_for('index'))
|
|
return render_template('new_problem.html')
|
|
|
|
@app.route('/problem/<int:problem_id>', methods=['GET', 'POST'])
|
|
def view_problem(problem_id):
|
|
problem = Problem.query.get_or_404(problem_id)
|
|
result = None
|
|
if request.method == 'POST':
|
|
user_code = request.form['user_code']
|
|
username = request.form.get('username', '').strip() or 'Anonymous'
|
|
import tracemalloc
|
|
tracemalloc.start()
|
|
run_result = run_code_against_tests(user_code, problem.test_code)
|
|
current, peak = tracemalloc.get_traced_memory()
|
|
tracemalloc.stop()
|
|
memory_used = peak // 1024 # in KB
|
|
# Try to get the last line number executed (even for successful runs)
|
|
line_number = None
|
|
import ast
|
|
try:
|
|
tree = ast.parse(user_code)
|
|
# Get the last line number in the user's code
|
|
if hasattr(tree, 'body') and tree.body:
|
|
last_node = tree.body[-1]
|
|
line_number = getattr(last_node, 'lineno', None)
|
|
except Exception:
|
|
pass
|
|
# If there was an error, try to get the error line number from the traceback
|
|
if run_result['error']:
|
|
tb = run_result['error']
|
|
import traceback
|
|
try:
|
|
tb_lines = traceback.extract_tb(traceback.TracebackException.from_string(tb).stack)
|
|
if tb_lines:
|
|
line_number = tb_lines[-1].lineno
|
|
except Exception:
|
|
pass
|
|
log_leaderboard(username, problem.id, run_result['runtime'], memory_used, line_number)
|
|
solution = Solution(problem_id=problem.id, user_code=user_code, passed=run_result['passed'], output=run_result['output'])
|
|
db.session.add(solution)
|
|
db.session.commit()
|
|
result = run_result
|
|
|
|
return render_template('problem.html', problem=problem, result=result)
|
|
|
|
if __name__ == '__main__':
|
|
app.run(debug=True)
|