init commit
This commit is contained in:
+55
@@ -0,0 +1,55 @@
|
|||||||
|
# Python bytecode and cache
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# Virtual environments
|
||||||
|
venv/
|
||||||
|
.venv/
|
||||||
|
env/
|
||||||
|
.env-env/
|
||||||
|
ENV/
|
||||||
|
|
||||||
|
# Django local settings & secrets
|
||||||
|
*.env
|
||||||
|
.env
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
local_settings.py
|
||||||
|
|
||||||
|
# Django media & static deployment folders
|
||||||
|
media/
|
||||||
|
staticfiles/
|
||||||
|
static-cdn/
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# Testing & coverage
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# OS-specific files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# IDEs & Editors
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
#temp
|
||||||
|
temp/
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class CheckProblemConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'check_problem'
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
from django import forms
|
||||||
|
|
||||||
|
class UploadFileForm(forms.Form):
|
||||||
|
title = forms.CharField(max_length=50)
|
||||||
|
newfile = forms.FileField()
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# Generated by Django 5.1.2 on 2024-12-17 14:35
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Resolvs',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('image', models.ImageField(upload_to='static/images/')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.2 on 2024-12-17 14:40
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('check_problem', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='resolvs',
|
||||||
|
name='image',
|
||||||
|
field=models.FileField(upload_to='media/images/'),
|
||||||
|
),
|
||||||
|
]
|
||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
# Generated by Django 5.1.2 on 2024-12-17 17:26
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('check_problem', '0002_alter_resolvs_image'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Problems',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('Name', models.CharField(max_length=100)),
|
||||||
|
('Description', models.CharField(max_length=1000)),
|
||||||
|
('Image', models.FileField(default='images/blank.png', upload_to='images/')),
|
||||||
|
('Price', models.IntegerField(default=1)),
|
||||||
|
('TimeLimit', models.IntegerField(default=1)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='resolvs',
|
||||||
|
name='image',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='resolvs',
|
||||||
|
name='DateTime',
|
||||||
|
field=models.DateField(default=datetime.datetime(2024, 12, 17, 17, 26, 46, 327422, tzinfo=datetime.timezone.utc)),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='resolvs',
|
||||||
|
name='SrcFile',
|
||||||
|
field=models.FileField(default=None, upload_to='Resolvs/'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='resolvs',
|
||||||
|
name='User',
|
||||||
|
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='resolvs',
|
||||||
|
name='Problem',
|
||||||
|
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.PROTECT, to='check_problem.problems'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tests',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('Input', models.CharField(max_length=1000)),
|
||||||
|
('Output', models.CharField(max_length=1000)),
|
||||||
|
('Problem', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='check_problem.problems')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 5.1.2 on 2024-12-17 18:15
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('check_problem', '0003_problems_remove_resolvs_image_resolvs_datetime_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='resolvs',
|
||||||
|
name='DateTime',
|
||||||
|
field=models.DateTimeField(auto_now_add=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='resolvs',
|
||||||
|
name='SrcFile',
|
||||||
|
field=models.FileField(default=None, upload_to='resolvs/'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Generated by Django 5.1.2 on 2024-12-19 17:00
|
||||||
|
|
||||||
|
import check_problem.models
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('check_problem', '0004_alter_resolvs_datetime_alter_resolvs_srcfile'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='resolvs',
|
||||||
|
name='Message',
|
||||||
|
field=models.CharField(default='', max_length=100),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='resolvs',
|
||||||
|
name='Status',
|
||||||
|
field=models.IntegerField(default=0),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='resolvs',
|
||||||
|
name='SrcFile',
|
||||||
|
field=models.FileField(default=None, upload_to=check_problem.models.upload_path),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 5.1.4 on 2025-01-03 05:31
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('check_problem', '0005_resolvs_message_resolvs_status_alter_resolvs_srcfile'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='resolvs',
|
||||||
|
name='CodeLen',
|
||||||
|
field=models.IntegerField(default=0),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='resolvs',
|
||||||
|
name='Time',
|
||||||
|
field=models.IntegerField(default=0),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
from django.db import models
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.utils import timezone
|
||||||
|
import os
|
||||||
|
|
||||||
|
class Problems(models.Model):
|
||||||
|
Name = models.CharField(max_length=100)
|
||||||
|
Description = models.CharField(max_length=1000)
|
||||||
|
Image = models.FileField(upload_to='images/',default='images/blank.png')
|
||||||
|
Price = models.IntegerField(default=1)
|
||||||
|
TimeLimit = models.IntegerField(default=1)
|
||||||
|
|
||||||
|
def upload_path(self,filename):
|
||||||
|
if self.User and self.Problem:
|
||||||
|
file_ext =filename[filename.rindex('.')+1:]
|
||||||
|
return f"resolvs/{self.User.id}/{self.Problem.id}.{file_ext}"
|
||||||
|
else:
|
||||||
|
return f"resolvs/{filename}"
|
||||||
|
|
||||||
|
class Resolvs(models.Model):
|
||||||
|
SrcFile = models.FileField(upload_to=upload_path, default=None)
|
||||||
|
User = models.ForeignKey(User, on_delete=models.PROTECT, default=None)
|
||||||
|
DateTime = models.DateTimeField(auto_now_add=True)
|
||||||
|
Problem = models.ForeignKey(Problems, on_delete=models.PROTECT, default=None)
|
||||||
|
Status = models.IntegerField(default=0)
|
||||||
|
Message = models.CharField(max_length=100,default="")
|
||||||
|
Time = models.IntegerField(default=0)
|
||||||
|
CodeLen = models.IntegerField(default=0)
|
||||||
|
def filename(self):
|
||||||
|
return self.SrcFile.name
|
||||||
|
|
||||||
|
class Tests(models.Model):
|
||||||
|
Problem = models.ForeignKey(Problems, on_delete=models.PROTECT)
|
||||||
|
Input = models.CharField(max_length=1000)
|
||||||
|
Output = models.CharField(max_length=1000)
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Document</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-size:20pt
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{{ user.username }} <a href="/logout">Выход</a> <a href="/">на главную</a>
|
||||||
|
<table>
|
||||||
|
{% for r in resolvs %}
|
||||||
|
<tr>
|
||||||
|
<td>{{u_list|dict_key:r}}</td><td>{{ext|dict_key:r}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Tavres: Решение задач</title>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.8/js/bootstrap.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.8/css/bootstrap.min.css" integrity="sha512-2bBQCjcnw658Lho4nlXJcc6WkV/UxpE/sAokbXPxQNGqmNdQrWqtw26Ns9kFF/yG792pKR1Sx8/Y1Lf1XN4GKA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.accordion-button {
|
||||||
|
--bs-accordion-active-bg: #e7bbce;
|
||||||
|
--bs-accordion-btn-bg: #9fe1f3;
|
||||||
|
font-size: 1.7rem;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
width: 100%;
|
||||||
|
text-align:center;
|
||||||
|
background-color: #080;
|
||||||
|
border-radius: 10px;
|
||||||
|
border:1px solid #000;
|
||||||
|
margin:0;
|
||||||
|
}
|
||||||
|
.main {
|
||||||
|
border: 2px solid #ccc;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
border: 2px solid #ccc;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
td:first-child {
|
||||||
|
border: 0px solid #ccc;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
th:first-child {
|
||||||
|
width: 30px;
|
||||||
|
}
|
||||||
|
.hide {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
h1 a {
|
||||||
|
color:#000;
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
.solved {
|
||||||
|
--bs-accordion-active-bg: #6fcba0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="navbar navbar-dark bg-dark box-shadow">
|
||||||
|
<div class="container d-flex justify-content-between">
|
||||||
|
<span class="navbar-brand d-flex align-items-center">{{ user.username }}</span>
|
||||||
|
<a href="logout" class="btn btn-primary my-2">Выход</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<main class="col-12">
|
||||||
|
<div class="accordion" id="accordionExample">
|
||||||
|
{% for p in problems %}
|
||||||
|
<div class="accordion-item">
|
||||||
|
<h2 class="accordion-header">
|
||||||
|
<button class="accordion-button collapsed {% if resolved|dict_key:p.id == 1 %}solved{% endif %}" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-{{p.id}}" aria-expanded="false" aria-controls="collapse-{{p.id}}">
|
||||||
|
{{ p.Name }}{% if resolved|dict_key:p.id == 1 %} (Решена){% endif %}
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div id="collapse-{{p.id}}" class="accordion-collapse collapse" data-bs-parent="#accordionExample">
|
||||||
|
<div class="accordion-body">
|
||||||
|
<a href="/pm/{{p.id}}/">подробнее</a>
|
||||||
|
{% autoescape off %}
|
||||||
|
<p>{{ p.Description }}</p>
|
||||||
|
{% endautoescape %}
|
||||||
|
|
||||||
|
<img src="{{ p.Image }}">
|
||||||
|
{% if resolved|dict_key:p.id == 1 %}
|
||||||
|
<p><b>Задача успешно решена</b></p>
|
||||||
|
<p><a href="{{ link|dict_key:p.id }}">Скачать решение</a></p>
|
||||||
|
|
||||||
|
<p><b>{{ message|dict_key:p.id }}</b></p>
|
||||||
|
{% else %}
|
||||||
|
<form method="POST" enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="file" name="resolve">
|
||||||
|
<input type="hidden" name="problem" value="{{ p.id }}">
|
||||||
|
<input type="submit">
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Tavres:Login user</title>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.8/js/bootstrap.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.8/css/bootstrap.min.css" integrity="sha512-2bBQCjcnw658Lho4nlXJcc6WkV/UxpE/sAokbXPxQNGqmNdQrWqtw26Ns9kFF/yG792pKR1Sx8/Y1Lf1XN4GKA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="modal fade show" style="display:block;">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<form method="POST">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Вход</h5>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="login" class="form-label">Имя пользователя:</label>
|
||||||
|
<input type="text" name="login" id="login" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="password" class="form-label">Пароль:</label>
|
||||||
|
<input type="password" name="password" id="password" class="form-control">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<a class="btn btn-secondary" href="/registration">Зарегистрироваться</a>
|
||||||
|
<button type="submit" class="btn btn-primary">Войти</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.8/js/bootstrap.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.8/css/bootstrap.min.css" integrity="sha512-2bBQCjcnw658Lho4nlXJcc6WkV/UxpE/sAokbXPxQNGqmNdQrWqtw26Ns9kFF/yG792pKR1Sx8/Y1Lf1XN4GKA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||||
|
<title>Tavres</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="modal fade show" style="display:block;">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<form method="POST">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Регистрация нового пользователя</h5>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="name" class="form-label">Имя пользователя:</label>
|
||||||
|
<input type="text" name="name" id="name" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="password" class="form-label">Пароль:</label>
|
||||||
|
<input type="password" name="password" id="password" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="email" class="form-label">E-mail:</label>
|
||||||
|
<input type="text" name="email" id="email" class="form-control">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="submit" class="btn btn-primary">Зарегистрироваться</button>
|
||||||
|
<a class="btn btn-secondary" href="/login">Вход</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
@@ -0,0 +1,185 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
from django.http import HttpResponse, HttpResponseRedirect
|
||||||
|
from django.contrib.auth import authenticate, login, logout
|
||||||
|
from django.template.defaultfilters import register
|
||||||
|
from .forms import UploadFileForm
|
||||||
|
from .models import *
|
||||||
|
import os
|
||||||
|
from subprocess import Popen, PIPE, STDOUT, call
|
||||||
|
import shutil
|
||||||
|
from django.conf import settings
|
||||||
|
import time
|
||||||
|
|
||||||
|
@register.filter(name='dict_key')
|
||||||
|
def dict_key(d, k):
|
||||||
|
return d[k]
|
||||||
|
|
||||||
|
def Index(request):
|
||||||
|
if request.user.is_authenticated:
|
||||||
|
user = User.objects.get(id = request.user.id)
|
||||||
|
else:
|
||||||
|
return HttpResponseRedirect('login/')
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
p_id = request.POST.get('problem')
|
||||||
|
problem = Problems.objects.get(id=p_id)
|
||||||
|
resolved = Resolvs.objects.filter(Problem=problem, Status=1, User=user).last()
|
||||||
|
if not problem or resolved:
|
||||||
|
return HttpResponseRedirect('/')
|
||||||
|
|
||||||
|
file = Resolvs(
|
||||||
|
SrcFile = request.FILES['resolve'],
|
||||||
|
User = user,
|
||||||
|
Problem = problem,
|
||||||
|
)
|
||||||
|
file.save()
|
||||||
|
file_ext =file.SrcFile.path[file.SrcFile.path.rindex('.')+1:]
|
||||||
|
if file_ext in ['py','cpp']:
|
||||||
|
#Запускаю проверку решения на корректность
|
||||||
|
tests = Tests.objects.filter(Problem=problem)
|
||||||
|
rt_dir = os.path.join(settings.TEMP_DIR,str(user.id))
|
||||||
|
if not os.path.exists(rt_dir):
|
||||||
|
os.mkdir(rt_dir)
|
||||||
|
shutil.copy(file.SrcFile.path, rt_dir+'/resolv.'+file_ext)
|
||||||
|
status = 1
|
||||||
|
message = ''
|
||||||
|
dt = 0
|
||||||
|
test_num = 0
|
||||||
|
for t in tests:
|
||||||
|
test_num += 1
|
||||||
|
stdout_data = ''
|
||||||
|
stderr_data = ''
|
||||||
|
|
||||||
|
with open(rt_dir+'/INPUT.TXT','w') as f:
|
||||||
|
f.write(t.Input)
|
||||||
|
#Запускаем отдельный процесс для проверки задачи
|
||||||
|
try:
|
||||||
|
startt = time.time()
|
||||||
|
if file_ext == 'py':
|
||||||
|
proc = Popen(['python',f'{rt_dir}\\resolv.py'], stdout=PIPE, stdin=PIPE, stderr=PIPE, text=True)
|
||||||
|
print(t.Input,f'{rt_dir}\\resolv.py')
|
||||||
|
stdout_data, stderr_data = proc.communicate(input=t.Input, timeout=20)
|
||||||
|
print(stdout_data, stderr_data)
|
||||||
|
elif file_ext == 'cpp':
|
||||||
|
if test_num == 1:
|
||||||
|
proc = call(f"g++ {rt_dir}/resolv.cpp",
|
||||||
|
cwd=rt_dir,
|
||||||
|
timeout=20,
|
||||||
|
shell=True)
|
||||||
|
proc = call(f"{rt_dir}/a.out",
|
||||||
|
cwd=rt_dir,
|
||||||
|
timeout=problem.TimeLimit,
|
||||||
|
shell=True)
|
||||||
|
endt = time.time()
|
||||||
|
tm = endt - startt
|
||||||
|
dt = tm if dt < tm else dt
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
status = 3
|
||||||
|
message = f"Выбили по таймауту"
|
||||||
|
break
|
||||||
|
#Проверяем корректность решения
|
||||||
|
if os.path.exists(rt_dir+'/OUTPUT.TXT'):
|
||||||
|
with open(rt_dir+'/OUTPUT.TXT','r') as f:
|
||||||
|
st = f.read()
|
||||||
|
if st != t.Output:
|
||||||
|
status = 3
|
||||||
|
message=f'Решение не верно. Тест {test_num}.'
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if stdout_data.strip() != t.Output:
|
||||||
|
status = 3
|
||||||
|
message=f'Решение не верно. Тест {test_num}.'
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
status = 9
|
||||||
|
message = "Неизвесный формат файла"
|
||||||
|
|
||||||
|
#Записываем результат в БД
|
||||||
|
file.Status = status
|
||||||
|
file.Message = message
|
||||||
|
file.Time = dt
|
||||||
|
file.save()
|
||||||
|
|
||||||
|
problems = Problems.objects.all()
|
||||||
|
dr = {}
|
||||||
|
dmessage = {}
|
||||||
|
link = {}
|
||||||
|
for p in problems:
|
||||||
|
resolv = Resolvs.objects.filter(User=user, Problem=p).last()
|
||||||
|
if resolv:
|
||||||
|
if resolv.Status == 1:
|
||||||
|
dr[p.id] = 1
|
||||||
|
dmessage[p.id] = ''
|
||||||
|
link[p.id] = resolv.SrcFile.url
|
||||||
|
else:
|
||||||
|
dr[p.id] = 0
|
||||||
|
dmessage[p.id] = resolv.Message
|
||||||
|
else:
|
||||||
|
dr[p.id] = 0
|
||||||
|
dmessage[p.id] = ''
|
||||||
|
return render(request,'index.html',{'problems':problems,
|
||||||
|
'user':user,
|
||||||
|
'resolved':dr,
|
||||||
|
'message':dmessage,
|
||||||
|
'link':link,})
|
||||||
|
def Details(request,p_id):
|
||||||
|
if request.user.is_authenticated:
|
||||||
|
user = User.objects.get(id = request.user.id)
|
||||||
|
else:
|
||||||
|
return HttpResponseRedirect('login/')
|
||||||
|
problem = Problems.objects.get(id=p_id)
|
||||||
|
resolvs = Resolvs.objects.filter(Problem=problem, Status=1)
|
||||||
|
res = []
|
||||||
|
usrs = {}
|
||||||
|
ext = {}
|
||||||
|
for r in resolvs:
|
||||||
|
res.append(r.id)
|
||||||
|
usrs[r.id] = r.User.username
|
||||||
|
ext[r.id] = os.path.splitext(r.SrcFile.name)[1][1:].upper()
|
||||||
|
return render(request,'details.html',{
|
||||||
|
'problem':problem,
|
||||||
|
'user':user,
|
||||||
|
'resolvs':res,
|
||||||
|
'u_list':usrs,
|
||||||
|
'ext':ext,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def Login(request):
|
||||||
|
if request.method == 'POST':
|
||||||
|
username = request.POST.get('login')
|
||||||
|
pwd = request.POST.get('password')
|
||||||
|
user = authenticate(request,username=username, password=pwd)
|
||||||
|
if user is not None:
|
||||||
|
login(request, user)
|
||||||
|
request.session['username'] = username
|
||||||
|
request.session.save()
|
||||||
|
return HttpResponseRedirect('/')
|
||||||
|
return render(request, 'login.html')
|
||||||
|
|
||||||
|
def Logout(request):
|
||||||
|
logout(request)
|
||||||
|
return HttpResponseRedirect('/')
|
||||||
|
|
||||||
|
def Registration(request):
|
||||||
|
if request.method == 'POST':
|
||||||
|
name = request.POST.get('name')
|
||||||
|
pwd = request.POST.get('password')
|
||||||
|
email = request.POST.get('email')
|
||||||
|
user = User.objects.filter(username = name).first()
|
||||||
|
if user:
|
||||||
|
print('Имя занято')
|
||||||
|
return render(request,'register.html')
|
||||||
|
user = User.objects.filter(email = email).first()
|
||||||
|
if user:
|
||||||
|
print('Email уже есть')
|
||||||
|
return render(request,'register.html')
|
||||||
|
user = User.objects.create_user(
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
pwd,
|
||||||
|
is_staff = True
|
||||||
|
)
|
||||||
|
return HttpResponseRedirect('/')
|
||||||
|
return render(request,'register.html')
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""Django's command-line utility for administrative tasks."""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run administrative tasks."""
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'olimp.settings')
|
||||||
|
try:
|
||||||
|
from django.core.management import execute_from_command_line
|
||||||
|
except ImportError as exc:
|
||||||
|
raise ImportError(
|
||||||
|
"Couldn't import Django. Are you sure it's installed and "
|
||||||
|
"available on your PYTHONPATH environment variable? Did you "
|
||||||
|
"forget to activate a virtual environment?"
|
||||||
|
) from exc
|
||||||
|
execute_from_command_line(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
ASGI config for olimp project.
|
||||||
|
|
||||||
|
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'olimp.settings')
|
||||||
|
|
||||||
|
application = get_asgi_application()
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
"""
|
||||||
|
Django settings for olimp project.
|
||||||
|
|
||||||
|
Generated by 'django-admin startproject' using Django 5.1.2.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/5.1/topics/settings/
|
||||||
|
|
||||||
|
For the full list of settings and their values, see
|
||||||
|
https://docs.djangoproject.com/en/5.1/ref/settings/
|
||||||
|
"""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
MEDIA_URL = '/media/'
|
||||||
|
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||||
|
TEMP_DIR = os.path.join(BASE_DIR,'temp')
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = 'django-insecure-o2mr5%=d062g(f2&4$8mm(f4@)qm#&&6do6i7ubhp#%)10x&le'
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = ['tavres.ru','127.0.0.1','localhost']
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
'check_problem',
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'olimp.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'olimp.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
"default": {
|
||||||
|
"ENGINE": "django.db.backends.sqlite3",
|
||||||
|
"NAME": BASE_DIR / "db.sqlite3",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/5.1/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
|
TIME_ZONE = 'UTC'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/5.1/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = 'static/'
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
"""
|
||||||
|
URL configuration for olimp project.
|
||||||
|
|
||||||
|
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||||
|
https://docs.djangoproject.com/en/5.1/topics/http/urls/
|
||||||
|
Examples:
|
||||||
|
Function views
|
||||||
|
1. Add an import: from my_app import views
|
||||||
|
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||||
|
Class-based views
|
||||||
|
1. Add an import: from other_app.views import Home
|
||||||
|
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||||
|
Including another URLconf
|
||||||
|
1. Import the include() function: from django.urls import include, path
|
||||||
|
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||||
|
"""
|
||||||
|
from django.contrib import admin
|
||||||
|
from django.urls import path
|
||||||
|
from django.conf.urls.static import static
|
||||||
|
from django.conf import settings
|
||||||
|
from check_problem.views import *
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('admin/', admin.site.urls),
|
||||||
|
path('',Index),
|
||||||
|
path('pm/<int:p_id>/',Details),
|
||||||
|
path('login/',Login),
|
||||||
|
path('logout/',Logout),
|
||||||
|
path('registration/',Registration),
|
||||||
|
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
WSGI config for olimp project.
|
||||||
|
|
||||||
|
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'olimp.settings')
|
||||||
|
|
||||||
|
application = get_wsgi_application()
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
import sqlite3
|
||||||
|
from pathlib import Path
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
ROOT_DIR = Path(__file__).resolve().parent
|
||||||
|
MEDIA_DIR = os.path.join(ROOT_DIR,'media')
|
||||||
|
TEMP_DIR = os.path.join(ROOT_DIR,'temp')
|
||||||
|
|
||||||
|
con = sqlite3.connect("db.sqlite3")
|
||||||
|
cur = con.cursor()
|
||||||
|
k=0
|
||||||
|
while k<3:
|
||||||
|
k+=1
|
||||||
|
res = cur.execute('''SELECT id,Problem_id,SrcFile
|
||||||
|
FROM check_problem_resolvs
|
||||||
|
WHERE Status='0';''')
|
||||||
|
res = res.fetchone()
|
||||||
|
if not res:
|
||||||
|
break
|
||||||
|
id = res[0]
|
||||||
|
p_id = res[1]
|
||||||
|
file_path = os.path.join(MEDIA_DIR,res[2])
|
||||||
|
file_ext =file_path[file_path.rindex('.')+1:]
|
||||||
|
if file_ext == 'py':
|
||||||
|
rt_dir = os.path.join(TEMP_DIR,str(id))
|
||||||
|
if not os.path.exists(rt_dir):
|
||||||
|
os.mkdir(rt_dir)
|
||||||
|
shutil.copy(file_path, rt_dir+'\\resolv.py')
|
||||||
|
res = cur.execute(f'''SELECT id,Input,Output
|
||||||
|
FROM check_problem_tests
|
||||||
|
WHERE Problem_id={p_id}''')
|
||||||
|
rows = res.fetchall()
|
||||||
|
status = 2
|
||||||
|
message='Все хорошо'
|
||||||
|
for row in rows:
|
||||||
|
with open(rt_dir+'\\INPUT.TXT','w') as f:
|
||||||
|
f.write(row[1])
|
||||||
|
try:
|
||||||
|
proc = subprocess.call(f"python {rt_dir}\\resolv.py",
|
||||||
|
cwd=rt_dir,
|
||||||
|
timeout=5)
|
||||||
|
except:
|
||||||
|
status = 3
|
||||||
|
message = "Выбили по таймауту"
|
||||||
|
break
|
||||||
|
if os.path.exists(rt_dir+'\\OUTPUT.TXT'):
|
||||||
|
with open(rt_dir+'\\OUTPUT.TXT','r') as f:
|
||||||
|
if f.read() != row[2]:
|
||||||
|
status = 3
|
||||||
|
message='Решение не верно'
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
status = 3
|
||||||
|
message = "Нет выходного файла"
|
||||||
|
break
|
||||||
|
cur.execute(f'''UPDATE check_problem_resolvs
|
||||||
|
SET Status='{status}', Message='{message}'
|
||||||
|
WHERE id='{id}';''')
|
||||||
|
con.commit()
|
||||||
|
else:
|
||||||
|
cur.execute(f'''UPDATE check_problem_resolvs
|
||||||
|
SET Status='9'
|
||||||
|
WHERE id='{id}';''')
|
||||||
|
con.commit()
|
||||||
|
con.close()
|
||||||
Reference in New Issue
Block a user