mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2024-09-21 08:23:20 +00:00
Accept Merge Request #91 : (virusdefender-dev -> dev)
Merge Request: 修改判题数据库 Created By: @virusdefender Accepted By: @virusdefender URL: https://coding.net/u/virusdefender/p/qduoj/git/merge/91
This commit is contained in:
commit
a9f4b370cc
@ -1,9 +1,7 @@
|
||||
# coding=utf-8
|
||||
import sys
|
||||
import os
|
||||
import pymongo
|
||||
|
||||
from bson.objectid import ObjectId
|
||||
import json
|
||||
import MySQLdb
|
||||
|
||||
from client import JudgeClient
|
||||
from language import languages
|
||||
@ -11,9 +9,7 @@ from compiler import compile_
|
||||
from result import result
|
||||
from settings import judger_workspace
|
||||
|
||||
sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
|
||||
|
||||
from judger_controller.settings import celery_mongodb_config, docker_mongodb_config
|
||||
from settings import submission_db
|
||||
|
||||
|
||||
# 简单的解析命令行参数
|
||||
@ -25,19 +21,31 @@ time_limit = args[4]
|
||||
memory_limit = args[6]
|
||||
test_case_id = args[8]
|
||||
|
||||
connection = pymongo.MongoClient(host=docker_mongodb_config["host"], port=docker_mongodb_config["port"])
|
||||
collection = connection["oj"]["oj_submission"]
|
||||
|
||||
submission = collection.find_one({"_id": ObjectId(submission_id)})
|
||||
if not submission:
|
||||
def db_conn():
|
||||
return MySQLdb.connect(db=submission_db["db"],
|
||||
user=submission_db["user"],
|
||||
passwd=submission_db["password"],
|
||||
host=submission_db["host"],
|
||||
port=submission_db["port"], charset="utf8")
|
||||
|
||||
|
||||
conn = db_conn()
|
||||
cur = conn.cursor()
|
||||
cur.execute("select language, code from submission where id = %s", (submission_id,))
|
||||
data = cur.fetchall()
|
||||
if not data:
|
||||
exit()
|
||||
connection.close()
|
||||
language_code = data[0][0]
|
||||
code = data[0][1]
|
||||
|
||||
conn.close()
|
||||
|
||||
# 将代码写入文件
|
||||
language = languages[submission["language"]]
|
||||
language = languages[language_code]
|
||||
src_path = judger_workspace + "run/" + language["src_name"]
|
||||
f = open(src_path, "w")
|
||||
f.write(submission["code"].encode("utf8"))
|
||||
f.write(code.encode("utf8"))
|
||||
f.close()
|
||||
|
||||
# 编译
|
||||
@ -45,23 +53,23 @@ try:
|
||||
exe_path = compile_(language, src_path, judger_workspace + "run/")
|
||||
except Exception as e:
|
||||
print e
|
||||
connection = pymongo.MongoClient(host=docker_mongodb_config["host"], port=docker_mongodb_config["port"])
|
||||
collection = connection["oj"]["oj_submission"]
|
||||
data = {"result": result["compile_error"], "info": str(e)}
|
||||
collection.find_one_and_update({"_id": ObjectId(submission_id)}, {"$set": data})
|
||||
connection.close()
|
||||
conn = db_conn()
|
||||
cur = conn.cursor()
|
||||
cur.execute("update submission set result=%s, info=%s where id=%s",
|
||||
(result["compile_error"], str(e), submission_id))
|
||||
conn.commit()
|
||||
exit()
|
||||
|
||||
print "Compile successfully"
|
||||
# 运行
|
||||
try:
|
||||
client = JudgeClient(language_code=submission["language"],
|
||||
client = JudgeClient(language_code=language_code,
|
||||
exe_path=exe_path,
|
||||
max_cpu_time=int(time_limit),
|
||||
max_real_time=int(time_limit) * 2,
|
||||
max_memory=int(memory_limit),
|
||||
test_case_dir=judger_workspace + "test_case/" + test_case_id + "/")
|
||||
judge_result = {"result": result["accepted"], "info": client.run()}
|
||||
judge_result = {"result": result["accepted"], "info": client.run(), "accepted_answer_time": None}
|
||||
|
||||
for item in judge_result["info"]:
|
||||
if item["result"]:
|
||||
@ -69,15 +77,23 @@ try:
|
||||
break
|
||||
else:
|
||||
l = sorted(judge_result["info"], key=lambda k: k["cpu_time"])
|
||||
judge_result["accepted_answer_info"] = {"time": l[-1]["cpu_time"]}
|
||||
judge_result["accepted_answer_time"] = l[-1]["cpu_time"]
|
||||
|
||||
except Exception as e:
|
||||
print e
|
||||
judge_result = {"result": result["system_error"], "info": str(e)}
|
||||
conn = db_conn()
|
||||
cur = conn.cursor()
|
||||
cur.execute("update submission set result=%s, info=%s where id=%s", (result["system_error"], str(e), submission_id))
|
||||
conn.commit()
|
||||
exit()
|
||||
|
||||
print "Run successfully"
|
||||
print judge_result
|
||||
connection = pymongo.MongoClient(host=docker_mongodb_config["host"], port=docker_mongodb_config["port"])
|
||||
collection = connection["oj"]["oj_submission"]
|
||||
collection.find_one_and_update({"_id": ObjectId(submission_id)}, {"$set": judge_result})
|
||||
connection.close()
|
||||
|
||||
conn = db_conn()
|
||||
cur = conn.cursor()
|
||||
cur.execute("update submission set result=%s, info=%s, accepted_answer_time=%s where id=%s",
|
||||
(judge_result["result"], json.dumps(judge_result["info"]), judge_result["accepted_answer_time"],
|
||||
submission_id))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
@ -15,3 +15,11 @@ lrun_gid = 1002
|
||||
judger_workspace = "/var/judger/"
|
||||
|
||||
|
||||
# 这个是在docker 中访问数据库 ip 不一定和web服务器还有celery的一样
|
||||
submission_db = {
|
||||
"host": "192.168.42.1",
|
||||
"port": 3306,
|
||||
"db": "oj_submission",
|
||||
"user": "root",
|
||||
"password": "mypwd"
|
||||
}
|
||||
|
@ -5,5 +5,3 @@ from .settings import redis_config
|
||||
|
||||
app = Celery("judge", broker='redis://%s:%s/%s' % (redis_config["host"], redis_config["port"], redis_config["db"]),
|
||||
include=["judge.judger_controller.tasks"])
|
||||
|
||||
Celery().conf.update(CELERY_ACCEPT_CONTENT = ['json'])
|
@ -7,7 +7,7 @@ redis_config = {
|
||||
|
||||
|
||||
docker_config = {
|
||||
"image_name": "d622347336b8",
|
||||
"image_name": " a7673b55d263",
|
||||
"docker_path": "docker",
|
||||
"shell": True
|
||||
}
|
||||
@ -17,16 +17,10 @@ test_case_dir = "/root/test_case/"
|
||||
source_code_dir = "/root/"
|
||||
|
||||
|
||||
celery_mongodb_config = {
|
||||
submission_db = {
|
||||
"host": "127.0.0.1",
|
||||
"username": "root",
|
||||
"password": "root",
|
||||
"port": 27017
|
||||
}
|
||||
|
||||
docker_mongodb_config = {
|
||||
"host": "192.168.42.1",
|
||||
"username": "root",
|
||||
"password": "root",
|
||||
"port": 27017
|
||||
"port": 3306,
|
||||
"db": "oj_submission",
|
||||
"user": "root",
|
||||
"password": "root"
|
||||
}
|
@ -1,11 +1,10 @@
|
||||
# coding=utf-8
|
||||
# from __future__ import absolute_import
|
||||
import MySQLdb
|
||||
import subprocess
|
||||
import pymongo
|
||||
from bson import ObjectId
|
||||
from ..judger.result import result
|
||||
from ..judger_controller.celery import app
|
||||
from settings import docker_config, source_code_dir, test_case_dir, celery_mongodb_config
|
||||
from settings import docker_config, source_code_dir, test_case_dir, submission_db
|
||||
|
||||
|
||||
@app.task
|
||||
@ -24,8 +23,16 @@ def judge(submission_id, time_limit, memory_limit, test_case_id):
|
||||
submission_id, str(time_limit), str(memory_limit), test_case_id)
|
||||
subprocess.call(command, shell=docker_config["shell"])
|
||||
except Exception as e:
|
||||
connection = pymongo.MongoClient(host=celery_mongodb_config["host"], port=celery_mongodb_config["port"])
|
||||
collection = connection["oj"]["oj_submission"]
|
||||
data = {"result": result["system_error"], "info": str(e)}
|
||||
collection.find_one_and_update({"_id": ObjectId(submission_id)}, {"$set": data})
|
||||
connection.close()
|
||||
print e
|
||||
conn = MySQLdb.connect(db=submission_db["db"],
|
||||
user=submission_db["user"],
|
||||
passwd=submission_db["password"],
|
||||
host=submission_db["host"],
|
||||
port=submission_db["port"],
|
||||
character="utf8")
|
||||
|
||||
cur = conn.cursor()
|
||||
cur.execute("update submission set result=%s, info=%s where id=%s",
|
||||
(result["system_error"], str(e), submission_id))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
30
oj/db_router.py
Normal file
30
oj/db_router.py
Normal file
@ -0,0 +1,30 @@
|
||||
# coding=utf-8
|
||||
|
||||
|
||||
class DBRouter(object):
|
||||
def db_for_read(self, model, **hints):
|
||||
if model._meta.app_label == 'submission':
|
||||
return 'submission'
|
||||
return "default"
|
||||
|
||||
def db_for_write(self, model, **hints):
|
||||
if model._meta.app_label == 'submission':
|
||||
return 'submission'
|
||||
return "default"
|
||||
|
||||
def allow_relation(self, obj1, obj2, **hints):
|
||||
return True
|
||||
|
||||
def allow_migrate(self, db, app_label, model=None, **hints):
|
||||
if app_label == "submission":
|
||||
if db == "submission":
|
||||
r = True
|
||||
else:
|
||||
r = False
|
||||
else:
|
||||
if db == "default":
|
||||
r = True
|
||||
else:
|
||||
r = False
|
||||
print db, app_label, r
|
||||
return r
|
@ -7,24 +7,27 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
# 下面是需要自己修改的
|
||||
LOG_PATH = "LOG/"
|
||||
|
||||
# 注意这是web 服务器访问的地址,判题度武器访问的地址不一定一样,因为可能不在一台机器上
|
||||
# 注意这是web 服务器访问的地址,判题端访问的地址不一定一样,因为可能不在一台机器上
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||
'CONN_MAX_AGE': 0.3,
|
||||
},
|
||||
'submission': {
|
||||
'NAME': 'oj_submission',
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'HOST': "121.42.32.129",
|
||||
'POST': 3306,
|
||||
'USER': 'root',
|
||||
'PASSWORD': 'mypwd'
|
||||
}
|
||||
}
|
||||
|
||||
# 这是web 服务器连接到mongodb 的地址
|
||||
MONGODB = {
|
||||
'HOST': '121.42.32.129',
|
||||
'USERNAME': 'root',
|
||||
'PASSWORD': 'root',
|
||||
'PORT': 27017
|
||||
}
|
||||
|
||||
DEBUG = True
|
||||
|
||||
# 同理 这是 web 服务器的上传路径
|
||||
TEST_CASE_DIR = os.path.join(BASE_DIR, 'test_case/')
|
||||
|
||||
DATABASE_ROUTERS = ['oj.db_router.DBRouter']
|
||||
|
||||
|
18
problem/migrations/0007_remove_problem_last_update_time.py
Normal file
18
problem/migrations/0007_remove_problem_last_update_time.py
Normal file
@ -0,0 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('problem', '0006_merge'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='problem',
|
||||
name='last_update_time',
|
||||
),
|
||||
]
|
@ -29,7 +29,7 @@ class AbstractProblem(models.Model):
|
||||
# 创建时间
|
||||
create_time = models.DateTimeField(auto_now_add=True)
|
||||
# 最后更新时间
|
||||
last_update_time = models.DateTimeField(auto_now=True)
|
||||
# last_update_time = models.DateTimeField(auto_now=True)
|
||||
# 这个题是谁创建的
|
||||
created_by = models.ForeignKey(User)
|
||||
# 来源
|
||||
|
@ -46,7 +46,7 @@ require(["jquery", "codeMirror", "csrfToken", "bsAlert"], function ($, codeMirro
|
||||
results[data.result].message +
|
||||
'! ';
|
||||
if (!data.result) {
|
||||
html += "CPU time: " + data.accepted_answer_info.time + "ms ";
|
||||
html += "CPU time: " + data.accepted_answer_time + "ms ";
|
||||
}
|
||||
html += ('<a href="/my_submission/' + submissionId + '/" target="_blank">查看详情</a></div> </div>');
|
||||
|
||||
|
32
submission/migrations/0001_initial.py
Normal file
32
submission/migrations/0001_initial.py
Normal file
@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import utils.shortcuts
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Submission',
|
||||
fields=[
|
||||
('id', models.CharField(default=utils.shortcuts.rand_str, max_length=32, serialize=False, primary_key=True, db_index=True)),
|
||||
('user_id', models.IntegerField()),
|
||||
('create_time', models.DateTimeField(auto_now_add=True)),
|
||||
('result', models.IntegerField(default=8)),
|
||||
('language', models.IntegerField()),
|
||||
('code', models.TextField()),
|
||||
('problem_id', models.IntegerField()),
|
||||
('info', models.TextField(null=True, blank=True)),
|
||||
('accepted_answer_time', models.IntegerField(null=True, blank=True)),
|
||||
('accepted_answer_info', models.TextField(null=True, blank=True)),
|
||||
],
|
||||
options={
|
||||
'db_table': 'submission',
|
||||
},
|
||||
),
|
||||
]
|
@ -1 +1,23 @@
|
||||
# coding=utf-8
|
||||
from django.db import models
|
||||
from utils.shortcuts import rand_str
|
||||
from judge.judger.result import result
|
||||
|
||||
|
||||
class Submission(models.Model):
|
||||
id = models.CharField(max_length=32, default=rand_str, primary_key=True, db_index=True)
|
||||
user_id = models.IntegerField()
|
||||
create_time = models.DateTimeField(auto_now_add=True)
|
||||
result = models.IntegerField(default=result["waiting"])
|
||||
language = models.IntegerField()
|
||||
code = models.TextField()
|
||||
problem_id = models.IntegerField()
|
||||
# 这个字段可能存储很多数据 比如编译错误、系统错误的时候,存储错误原因字符串
|
||||
# 正常运行的时候存储 lrun 的判题结果,比如cpu时间内存之类的
|
||||
info = models.TextField(blank=True, null=True)
|
||||
accepted_answer_time = models.IntegerField(blank=True, null=True)
|
||||
# 这个字段只有在题目是accepted 的时候才会用到,比赛题目的提交可能还会有得分等信息,存储在这里面
|
||||
accepted_answer_info = models.TextField(blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = "submission"
|
||||
|
@ -1,28 +1,19 @@
|
||||
# coding=utf-8
|
||||
import datetime
|
||||
import pymongo
|
||||
from bson.objectid import ObjectId
|
||||
import json
|
||||
|
||||
from django.shortcuts import render
|
||||
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from judge.judger.result import result
|
||||
from judge.judger_controller.tasks import judge
|
||||
from account.decorators import login_required
|
||||
from problem.models import Problem
|
||||
from utils.shortcuts import serializer_invalid_response, error_response, success_response, error_page
|
||||
from .models import Submission
|
||||
from .serializers import CreateSubmissionSerializer
|
||||
|
||||
|
||||
def _create_mongodb_connection():
|
||||
mongodb_setting = settings.MONGODB
|
||||
connection = pymongo.MongoClient(host=mongodb_setting["HOST"], port=mongodb_setting["PORT"])
|
||||
return connection["oj"]["oj_submission"]
|
||||
|
||||
|
||||
class SubmissionAPIView(APIView):
|
||||
@login_required
|
||||
def post(self, request):
|
||||
@ -34,23 +25,19 @@ class SubmissionAPIView(APIView):
|
||||
serializer = CreateSubmissionSerializer(data=request.data)
|
||||
if serializer.is_valid():
|
||||
data = serializer.data
|
||||
# data["language"] = int(data["language"])
|
||||
data["user_id"] = request.user.id
|
||||
data["result"] = result["waiting"]
|
||||
data["create_time"] = datetime.datetime.now()
|
||||
try:
|
||||
problem = Problem.objects.get(id=data["problem_id"])
|
||||
except Problem.DoesNotExist:
|
||||
return error_response(u"题目不存在")
|
||||
collection = _create_mongodb_connection()
|
||||
submission_id = str(collection.insert_one(data).inserted_id)
|
||||
submission = Submission.objects.create(user_id=request.user.id, language=int(data["language"]),
|
||||
code=data["code"], problem_id=problem.id)
|
||||
|
||||
try:
|
||||
judge.delay(submission_id, problem.time_limit, problem.memory_limit, problem.test_case_id)
|
||||
judge.delay(submission.id, problem.time_limit, problem.memory_limit, problem.test_case_id)
|
||||
except Exception:
|
||||
return error_response(u"提交判题任务失败")
|
||||
|
||||
return success_response({"submission_id": submission_id})
|
||||
return success_response({"submission_id": submission.id})
|
||||
else:
|
||||
return serializer_invalid_response(serializer)
|
||||
|
||||
@ -59,41 +46,36 @@ class SubmissionAPIView(APIView):
|
||||
submission_id = request.GET.get("submission_id", None)
|
||||
if not submission_id:
|
||||
return error_response(u"参数错误")
|
||||
submission = _create_mongodb_connection().find_one({"_id": ObjectId(submission_id), "user_id": request.user.id})
|
||||
if submission:
|
||||
response_data = {"result": submission["result"]}
|
||||
if submission["result"] == 0:
|
||||
response_data["accepted_answer_info"] = submission["accepted_answer_info"]
|
||||
return success_response(response_data)
|
||||
else:
|
||||
try:
|
||||
submission = Submission.objects.get(id=submission_id, user_id=request.user.id)
|
||||
except Submission.DoesNotExist:
|
||||
return error_response(u"提交不存在")
|
||||
response_data = {"result": submission.result}
|
||||
if submission.result == 0:
|
||||
response_data["accepted_answer_time"] = submission.accepted_answer_time
|
||||
return success_response(response_data)
|
||||
|
||||
|
||||
@login_required
|
||||
def problem_my_submissions_list_page(request, problem_id):
|
||||
collection = _create_mongodb_connection()
|
||||
submissions = collection.find({"problem_id": int(problem_id), "user_id": request.user.id},
|
||||
projection=["result", "accepted_answer_info", "create_time", "language"],
|
||||
sort=[["create_time", -pymongo.ASCENDING]])
|
||||
try:
|
||||
problem = Problem.objects.get(id=problem_id, visible=True)
|
||||
except Problem.DoesNotExist:
|
||||
return error_page(request, u"问题不存在")
|
||||
submissions = Submission.objects.filter(user_id=request.user.id, problem_id=problem.id).order_by("-create_time")
|
||||
return render(request, "oj/problem/my_submissions_list.html",
|
||||
{"submissions": submissions, "problem": problem})
|
||||
|
||||
|
||||
@login_required
|
||||
def my_submission(request, submission_id):
|
||||
collection = _create_mongodb_connection()
|
||||
submission = collection.find_one({"user_id": request.user.id, "_id": ObjectId(submission_id)},
|
||||
projection=["result", "accepted_answer_info", "create_time",
|
||||
"language", "code", "problem_id", "info"])
|
||||
if not submission:
|
||||
try:
|
||||
submission = Submission.objects.get(id=submission_id)
|
||||
except Submission.DoesNotExist:
|
||||
return error_page(request, u"提交不存在")
|
||||
try:
|
||||
problem = Problem.objects.get(id=submission["problem_id"], visible=True)
|
||||
problem = Problem.objects.get(id=submission.problem_id, visible=True)
|
||||
except Problem.DoesNotExist:
|
||||
return error_page(request, u"提交不存在")
|
||||
|
||||
return render(request, "oj/problem/my_submission.html", {"submission": submission, "problem": problem})
|
||||
return render(request, "oj/problem/my_submission.html",
|
||||
{"submission": submission, "problem": problem})
|
@ -15,11 +15,15 @@
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="form-group"><label>时间限制(ms)</label>
|
||||
|
||||
<input type="number" name="timeLimit" class="form-control" ms-duplex="timeLimit">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="form-group"><label>内存限制(MB)</label>
|
||||
|
||||
|
||||
<input type="number" name="memoryLimit" class="form-control" ms-duplex="memoryLimit">
|
||||
</div>
|
||||
</div>
|
||||
|
@ -22,7 +22,7 @@
|
||||
</span>
|
||||
</h4>
|
||||
{% ifequal submission.result 0 %}
|
||||
<p>时间 : {{ submission.accepted_answer_info.time }}ms 语言 :
|
||||
<p>时间 : {{ submission.accepted_answer_time }}ms 语言 :
|
||||
{{ submission.language|translate_language }}
|
||||
</p>
|
||||
{% endifequal %}
|
||||
|
@ -28,12 +28,12 @@
|
||||
<tbody>
|
||||
{% for item in submissions %}
|
||||
<tr class="{{ item.result|translate_result_class }}">
|
||||
<th scope="row"><a href="/my_submission/{{ item|translate_id }}/">{{ forloop.counter }}</a></th>
|
||||
<th scope="row"><a href="/my_submission/{{ item.id }}/">{{ forloop.counter }}</a></th>
|
||||
<td>{{ item.create_time }}</td>
|
||||
<td>{{ item.result|translate_result }}</td>
|
||||
<td>
|
||||
{% if item.accepted_answer_info.time %}
|
||||
{{ item.accepted_answer_info.time }}ms
|
||||
{% if item.accepted_answer_time %}
|
||||
{{ item.accepted_answer_time }}ms
|
||||
{% else %}
|
||||
--
|
||||
{% endif %}
|
||||
|
@ -17,10 +17,6 @@ def translate_result(value):
|
||||
return results[value]
|
||||
|
||||
|
||||
def translate_id(submission_item):
|
||||
return submission_item["_id"]
|
||||
|
||||
|
||||
def translate_language(value):
|
||||
return {1: "C", 2: "C++", 3: "Java"}[value]
|
||||
|
||||
@ -35,6 +31,5 @@ def translate_result_class(value):
|
||||
|
||||
register = template.Library()
|
||||
register.filter("translate_result", translate_result)
|
||||
register.filter("translate_id", translate_id)
|
||||
register.filter("translate_language", translate_language)
|
||||
register.filter("translate_result_class", translate_result_class)
|
Loading…
Reference in New Issue
Block a user