├── .gitignore ├── README.md ├── config.py ├── create_db.py ├── requirements.txt ├── run.py ├── syzoj-judge ├── judge.py └── runner ├── syzoj ├── __init__.py ├── controller.py ├── models │ ├── __init__.py │ ├── article.py │ ├── contest.py │ ├── file.py │ ├── judge.py │ ├── problem.py │ └── user.py ├── static │ ├── amazeui.min.css │ ├── amazeui.min.js │ ├── auto-render.js │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── jquery.ext.js │ ├── jquery.min.js │ ├── marked.js │ ├── prettify.css │ ├── prettify.js │ ├── syzoj-logo.png │ └── syzoj_32.ico ├── templates │ ├── article.html │ ├── contest.html │ ├── contest_list.html │ ├── contest_problem.html │ ├── contest_ranklist.html │ ├── delete_article.html │ ├── discussion.html │ ├── edit_article.html │ ├── edit_contest.html │ ├── edit_problem.html │ ├── edit_user.html │ ├── error_info.html │ ├── index.html │ ├── judge_detail.html │ ├── judge_state.html │ ├── layout.html │ ├── login.html │ ├── problem.html │ ├── problem_set.html │ ├── ranklist.html │ ├── sign_up.html │ ├── submit.html │ ├── upload_testdata.html │ ├── user.html │ └── virtual_contest.html ├── update_assistant │ └── misc.py └── views │ ├── __init__.py │ ├── common.py │ ├── contest.py │ ├── discussion.py │ ├── judge.py │ ├── problem.py │ ├── session.py │ └── user.py └── test ├── test_contest.py ├── test_controller.py └── test_problem.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | Include 3 | Lib 4 | Scripts 5 | .idea 6 | test.db 7 | *.zip 8 | .settings 9 | /syzoj/static/uploads/* 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | It's deprecated! [SYZOJ2](https://github.com/syzoj/syzoj) is also a choice for you. 2 | 3 | SYZOJ2 is maintained by [@Menci](https://github.com/Menci) now. Menci is a nice and skilled developer, I believe he will make SYZOJ better. SYZOJ2 is written in node.js, it has good organization and clean code. 4 | 5 | Thanks for Fmuckss and who has made the contributions to SYZOJ. 6 | 7 | --Chenyao2333 8 | 9 | ~~This project for me to practice Python, it's with many bugs and bad code style now.~~ 10 | 11 | # ~~syzoj~~ 12 | ~~An OnlineJudge System for OI and ACM/icpc.~~ 13 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | BASE_DIR = os.path.abspath(os.path.dirname(__file__)) 4 | SQLALCHEMY_DATABASE_URI = "mysql://root:syzojsyzoj@127.0.0.1/syzoj" 5 | UPLOAD_FOLDER = os.path.join(BASE_DIR, "syzoj", "static", "uploads") 6 | JUDGE_TOKEN = "77783949202395150352388871624955475980489287735056" 7 | 8 | if not os.path.isdir(UPLOAD_FOLDER): 9 | os.mkdir(UPLOAD_FOLDER) 10 | -------------------------------------------------------------------------------- /create_db.py: -------------------------------------------------------------------------------- 1 | from syzoj import db 2 | 3 | db.drop_all() 4 | db.create_all() 5 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | flask < 1 2 | flask-sqlalchemy >= 2 3 | mysql-python 4 | -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | from syzoj import oj 2 | 3 | if __name__ == '__main__': 4 | oj.debug = True 5 | oj.run(host="0.0.0.0", port=8811) 6 | -------------------------------------------------------------------------------- /syzoj-judge/judge.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #!/usr/bin/python 3 | import os 4 | import time 5 | import zipfile 6 | import urllib 7 | import urllib2 8 | import json 9 | import ExTJudger 10 | import codecs 11 | import subprocess 12 | from random import randint 13 | 14 | _SYZOJ_URL = "http://localhost:8811" 15 | _DOWNLOAD_TESTDATA_URL = _SYZOJ_URL + "/static/uploads" 16 | _GET_TASK_URL = _SYZOJ_URL + "/api/waiting_judge" 17 | _UPLOAD_TASK_URL = _SYZOJ_URL + "/api/update_judge" 18 | _SESSION_ID = "77783949202395150352388871624955475980489287735056" 19 | _BASE_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__))) 20 | _TESTDATA_DIR = os.path.join(_BASE_DIR, "testdata") 21 | 22 | if not os.path.isdir(_TESTDATA_DIR): 23 | os.mkdir(_TESTDATA_DIR) 24 | 25 | 26 | def get_judge_task(): 27 | global _GET_TASK_URL, _SESSION_ID 28 | url = _GET_TASK_URL + "?" + urllib.urlencode({"session_id": _SESSION_ID}) 29 | task = urllib2.urlopen(url).read() 30 | return json.loads(task) 31 | 32 | 33 | def upload_judge_result(result, judge_id): 34 | global _UPLOAD_TASK_URL, _SESSION_ID 35 | url = _UPLOAD_TASK_URL + "/" + str(judge_id) + "?" + urllib.urlencode({"session_id": _SESSION_ID}) 36 | data = urllib.urlencode({"result": json.dumps(result)}) 37 | req = urllib2.Request(url, data) 38 | response = urllib2.urlopen(req) 39 | return response.read() 40 | 41 | 42 | def download_file(url, des): 43 | df = urllib2.urlopen(url) 44 | with open(des, "a") as f: 45 | while True: 46 | data = df.read(4096) 47 | if data: 48 | f.write(data) 49 | else: 50 | break 51 | df.close() 52 | 53 | 54 | def unzip_as_testdata(testdata, des_dir): 55 | if not os.path.isdir(des_dir): 56 | os.mkdir(des_dir) 57 | 58 | zip_file = zipfile.ZipFile(testdata) 59 | 60 | for name in zip_file.namelist(): 61 | with open(os.path.join(des_dir, name), "wb") as f: 62 | f.write(zip_file.read(name)) 63 | f.close() 64 | 65 | zip_file.close() 66 | 67 | 68 | def get_testdata_dir(testdata_name): 69 | global _TESTDATA_DIR, _DOWNLOAD_TESTDATA_URL 70 | testdata_dir = os.path.join(_TESTDATA_DIR, testdata_name) 71 | if os.path.isdir(testdata_dir): 72 | return testdata_dir 73 | 74 | tmp_zip_file = _TESTDATA_DIR + testdata_name + "_tmp.zip" 75 | download_file(_DOWNLOAD_TESTDATA_URL + "/" + testdata_name, tmp_zip_file) 76 | unzip_as_testdata(tmp_zip_file, testdata_dir) 77 | os.remove(tmp_zip_file) 78 | 79 | return testdata_dir 80 | 81 | 82 | def write_src(source, target): 83 | if os.path.isfile(target): 84 | os.remove(target) 85 | with codecs.open(target, "w", "utf-8") as f: 86 | f.write(source) 87 | 88 | 89 | def run(source_file, std_in, std_out, time_limit, memory_limit): 90 | user_out = "user_tmp.out" 91 | 92 | CFG = { 93 | 'language':'C++', 94 | 'source_name':source_file, 95 | 'in_file':std_in, 96 | 'out_file':user_out, 97 | 'ans_file':std_out, 98 | 'time_limit':time_limit, 99 | 'memory_limit':memory_limit, 100 | 'compile option':['-lm', '-DONLINE_JUDGE'] 101 | } 102 | 103 | res = ExTJudger.run(CFG) 104 | 105 | result = {} 106 | result['status'] = res['status'] 107 | 108 | if not 'use_time' in res: 109 | result['time_used'] = 0 110 | else: 111 | result["time_used"] = res["use_time"] 112 | if not 'use_memory' in res: 113 | result['memory_used'] = 0 114 | else: 115 | result["memory_used"] = res["use_memory"] 116 | 117 | result['score'] = res['score'] 118 | 119 | if 'in' in res: 120 | result["input"] = res['in'][0: min(120, len(res['in']))] 121 | if len(res['in']) > 120: 122 | result["input"] += '\n...' 123 | if 'ans' in res: 124 | result["answer"] = res['ans'][0: min(120, len(res['ans']))] 125 | if len(res['ans']) > 120: 126 | result["answer"] += '\n...' 127 | if 'out' in res: 128 | result["user_out"] = res['out'][0: min(120, len(res['out']))] 129 | if len(res['out']) > 120: 130 | result["user_out"] += '\n...' 131 | if 'compile_info' in res: 132 | result['compile_info'] = res['compile_info'] 133 | if len(res['compile_info']) > 256: 134 | result["compile_info"] += '\n...' 135 | 136 | if os.path.isfile(user_out): 137 | os.remove(user_out) 138 | return result 139 | 140 | 141 | def judge(source, time_limit, memory_limit, testdata): 142 | result = {"status": "Judging", "score": 0, "total_time": 0, "max_memory": 0, "case_num": 0} 143 | target = "tjudger_source_file.cpp" 144 | 145 | testdata_dir = get_testdata_dir(testdata) 146 | 147 | write_src(source, target) 148 | 149 | with open(os.path.join(testdata_dir, "data_rule.txt")) as f: 150 | data_rule = f.read() 151 | lines = data_rule.split('\n') 152 | for i in range(0, len(lines)): 153 | lines[i] = lines[i].replace('\r', '').replace('\n', '') 154 | dt_no = lines[0].split() 155 | std_in = lines[1] 156 | std_out = lines[2] 157 | 158 | for i, no in enumerate(dt_no): 159 | std_in_file = os.path.join(testdata_dir, std_in.replace("#", str(no))) 160 | std_out_file = os.path.join(testdata_dir, std_out.replace("#", str(no))) 161 | 162 | res = run(target, std_in_file, std_out_file, time_limit, memory_limit) 163 | 164 | if res['status'] == "Compile Error": 165 | result['compiler_output'] = res['compile_info'] 166 | result['status'] = "Compile Error" 167 | return result 168 | 169 | result[i] = res 170 | result["case_num"] += 1 171 | result["total_time"] += res["time_used"] 172 | if res["memory_used"] > result["max_memory"]: 173 | result["max_memory"] = res["memory_used"] 174 | 175 | if res["status"] == "Accepted": 176 | result["score"] += 1.0 / len(dt_no) * res['score'] 177 | elif result["status"] == "Judging": 178 | result["status"] = res["status"] 179 | 180 | result["score"] = int(result["score"] + 0.1) 181 | if result["status"] == "Judging": 182 | result["status"] = "Accepted" 183 | return result 184 | 185 | 186 | def main(): 187 | while True: 188 | time.sleep(1) 189 | task = get_judge_task() 190 | if not task["have_task"]: 191 | continue 192 | 193 | try: 194 | result = judge(task["code"], task["time_limit"], task["memory_limit"], task["testdata"]) 195 | except: 196 | result = {"status": "System Error", "score": 0, "total_time": 0, "max_memory": 0, "case_num": 0} 197 | 198 | upload_judge_result(result, task["judge_id"]) 199 | 200 | 201 | def test_connect_to_server(): 202 | task = get_judge_task() 203 | testdata_dir = get_testdata_dir(task["testdata"]) 204 | print task 205 | print testdata_dir 206 | print upload_judge_result({"status": "System Error", "score": 0, "total_time": 0, "max_memory": 0, "case_num": 0}, 207 | task["judge_id"]) 208 | 209 | 210 | if __name__ == '__main__': 211 | # test_connect_to_server() 212 | # main() 213 | while True: 214 | try: 215 | main() 216 | except: 217 | pass 218 | -------------------------------------------------------------------------------- /syzoj-judge/runner: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhengzhou-11-Highschool/syzoj/b3dff67d716f754528ad65531ed9cb7b3d06d01a/syzoj-judge/runner -------------------------------------------------------------------------------- /syzoj/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_sqlalchemy import SQLAlchemy 3 | 4 | oj = Flask(__name__) 5 | oj.config.from_object("config") 6 | db = SQLAlchemy(oj) 7 | 8 | import views, models, controller 9 | -------------------------------------------------------------------------------- /syzoj/controller.py: -------------------------------------------------------------------------------- 1 | from syzoj.models import User, Problem 2 | from urllib import urlencode 3 | import time, re 4 | 5 | 6 | class Tools(object): 7 | @staticmethod 8 | def pretty_time(t): 9 | return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(t)) 10 | 11 | @staticmethod 12 | def to_str(s): 13 | return str(s) 14 | 15 | @staticmethod 16 | def url_encode(query, doseq=0): 17 | return urlencode(query, doseq) 18 | 19 | @staticmethod 20 | def get_cur_user(): 21 | return User.get_cur_user() 22 | 23 | 24 | class Checker(object): 25 | @staticmethod 26 | def is_valid_username(username): 27 | if not username: 28 | return False 29 | 30 | if len(username) < 3 or len(username) > 16: 31 | return False 32 | 33 | checker = re.compile("[A-Za-z0-9_]") 34 | if not checker.match(username): 35 | return False 36 | 37 | return True 38 | 39 | @staticmethod 40 | def is_valid_email(email): 41 | if not email: 42 | return False 43 | 44 | if len(email) < 3 or len(email) > 50: 45 | return False 46 | 47 | checker = re.compile("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$") 48 | if not checker.match(email): 49 | return False 50 | 51 | return True 52 | 53 | @staticmethod 54 | def is_valid_password(password): 55 | if not password: 56 | return None 57 | 58 | # Because of the salt is "syzoj2_xxx" and the "syzoj2_xxx" 's md5 is"59cb..." 59 | # the empty password 's md5 will equal "59cb.." 60 | syzoj2_xxx_md5 = "59cb65ba6f9ad18de0dcd12d5ae11bd2" 61 | if password == syzoj2_xxx_md5: 62 | return False 63 | 64 | return True 65 | 66 | 67 | class Paginate(): 68 | query = None 69 | total_page = 0 70 | per_page = 10 71 | cur_page = 1 72 | edge_display_num = 10 73 | make_url = None 74 | other = None 75 | 76 | def __init__(self, query, make_url=None, other=None, cur_page=1, per_page=10, edge_display_num=2): 77 | if not cur_page: 78 | cur_page = 1 79 | self.cur_page = int(cur_page) 80 | self.per_page = per_page 81 | self.edge_display_num = edge_display_num 82 | self.query = query 83 | self.make_url = make_url 84 | self.other = other 85 | total = query.count() 86 | self.total_page = total / per_page 87 | if total % per_page: 88 | self.total_page += 1 89 | 90 | def have_pre(self, cur_page=None): 91 | if not cur_page: 92 | cur_page = self.cur_page 93 | print cur_page > 1 94 | return cur_page > 1 95 | 96 | def have_next(self, cur_page=None): 97 | if not cur_page: 98 | cur_page = self.cur_page 99 | return cur_page < self.total_page 100 | 101 | def need_omit_left(self): 102 | return self.cur_page - self.edge_display_num > 1 103 | 104 | def need_omit_right(self): 105 | return self.cur_page + self.edge_display_num < self.total_page 106 | 107 | def range(self): 108 | start = self.cur_page - self.edge_display_num 109 | stop = self.cur_page + self.edge_display_num + 1 110 | if start < 1: 111 | start = 1 112 | if stop > self.total_page + 1: 113 | stop = self.total_page + 1 114 | return range(start, stop) 115 | 116 | def get(self): 117 | return self.query.offset((self.cur_page - 1) * self.per_page).limit(self.per_page) 118 | 119 | def get_html(self): 120 | pre_disable = "" 121 | next_disable = "" 122 | left_omit = "" 123 | right_omit = "" 124 | pre_url = "" 125 | next_url = "" 126 | pid_list = "" 127 | 128 | if self.have_pre(): 129 | pre_url = self.make_url(self.cur_page - 1, self.other) 130 | else: 131 | pre_disable = "am-disabled" 132 | if self.have_next(): 133 | next_url = self.make_url(self.cur_page + 1, self.other) 134 | else: 135 | next_disable = "am-disabled" 136 | 137 | if self.need_omit_left(): 138 | left_omit = '''
  • ...
  • ''' 139 | if self.need_omit_right(): 140 | right_omit = '''
  • ...
  • ''' 141 | 142 | for pid in self.range(): 143 | active = "" 144 | if pid == self.cur_page: 145 | active = "am-active" 146 | pid_list += '''
  • ''' + str(pid) + '''
  • ''' 148 | 149 | html = '''
    150 | 159 |
    ''' 160 | return html 161 | 162 | 163 | def register(username, password, email): 164 | state_code = 0 165 | if not Checker.is_valid_username(username): 166 | state_code = 2002 167 | elif not Checker.is_valid_password(password): 168 | state_code = 2007 169 | elif not Checker.is_valid_password(email): 170 | state_code = 2006 171 | elif User.query.filter_by(username=username).first(): 172 | state_code = 2008 173 | else: 174 | state_code = 1 175 | user = User(username=username, password=password, email=email) 176 | user.save() 177 | return state_code 178 | 179 | 180 | def create_problem(user, title): 181 | problem = Problem(user=user, title=title) 182 | problem.save() 183 | print problem 184 | return problem.id 185 | 186 | 187 | def become_admin(user): 188 | user.is_admin = True 189 | user.save() 190 | 191 | 192 | def cancel_admin(user): 193 | user.is_admin = False 194 | user.save() 195 | -------------------------------------------------------------------------------- /syzoj/models/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from .user import * 3 | from .problem import * 4 | from .judge import * 5 | from .contest import * 6 | from .article import * 7 | from .file import * -------------------------------------------------------------------------------- /syzoj/models/article.py: -------------------------------------------------------------------------------- 1 | from syzoj import db 2 | import time 3 | 4 | tags_table = db.Table('article_tags', 5 | db.Column('tag_id', db.Integer, db.ForeignKey('article_tag.id'), index=True), 6 | db.Column('article_id', db.Integer, db.ForeignKey('article.id'), index=True) 7 | ) 8 | 9 | 10 | class ArticleTag(db.Model): 11 | id = db.Column(db.Integer, primary_key=True) 12 | name = db.Column(db.String(80), index=True) 13 | 14 | def __init__(self, name): 15 | self.name = name 16 | 17 | def __repr__(self): 18 | return "" % self.name 19 | 20 | def save(self): 21 | db.session.add(self) 22 | db.session.commit() 23 | 24 | 25 | class Article(db.Model): 26 | id = db.Column(db.Integer, primary_key=True) 27 | title = db.Column(db.String(80)) 28 | content = db.Column(db.Text) 29 | 30 | user_id = db.Column(db.Integer, db.ForeignKey("user.id"), index=True) 31 | user = db.relationship("User", backref=db.backref("articles", lazy='dynamic')) 32 | 33 | public_time = db.Column(db.Integer) # googbye at 2038-1-19 34 | update_time = db.Column(db.Integer) 35 | sort_time = db.Column(db.Integer, index=True) 36 | 37 | tags = db.relationship('ArticleTag', secondary=tags_table, 38 | backref=db.backref('articles', lazy='dynamic')) 39 | 40 | comments_num = db.Column(db.Integer) 41 | allow_comment = db.Column(db.Boolean) 42 | 43 | def __init__(self, title, content, user, allow_comment=True, public_time=None): 44 | if not public_time: 45 | public_time = int(time.time()) 46 | self.title = title 47 | self.content = content 48 | self.user = user 49 | self.public_time = public_time 50 | self.update_time = public_time 51 | self.sort_time = public_time 52 | self.comments_num = 0 53 | self.allow_comment = allow_comment 54 | 55 | 56 | def __repr__(self): 57 | return "
    " % self.title 58 | 59 | def save(self): 60 | db.session.add(self) 61 | db.session.commit() 62 | 63 | def delete(self): 64 | db.session.delete(self) 65 | db.session.commit() 66 | 67 | def is_allowed_edit(self, user=None): 68 | if not user: 69 | return False 70 | if user.id == self.user_id: 71 | return True 72 | if user.have_privilege(6): 73 | return True 74 | return False 75 | 76 | 77 | class Comment(db.Model): 78 | id = db.Column(db.Integer, primary_key=True) 79 | content = db.Column(db.Text) 80 | 81 | article_id = db.Column(db.Integer, db.ForeignKey("article.id"), index=True) 82 | article = db.relationship("Article", backref=db.backref("comments", lazy='dynamic')) 83 | 84 | user_id = db.Column(db.Integer, db.ForeignKey("user.id"), index=True) 85 | user = db.relationship("User", backref=db.backref("comments", lazy='dynamic')) 86 | 87 | public_time = db.Column(db.Integer) # googbye at 2038-1-19 88 | 89 | def __init__(self, content, article, user, public_time=None): 90 | if not public_time: 91 | public_time = int(time.time()) 92 | self.content = content 93 | self.article = article 94 | self.user = user 95 | self.public_time = public_time 96 | 97 | 98 | def __repr__(self): 99 | return "" % self.content 100 | 101 | def save(self): 102 | db.session.add(self) 103 | db.session.commit() 104 | -------------------------------------------------------------------------------- /syzoj/models/contest.py: -------------------------------------------------------------------------------- 1 | from syzoj import db 2 | from syzoj.models.problem import Problem 3 | import time 4 | import json 5 | 6 | 7 | class ContestRanklist(db.Model): 8 | """ 9 | save ranklist as json 10 | follow is ranklist structure 11 | { 12 | "player_num": player_num 13 | 1: the ContestPlayer's id of rank1 14 | 2: the ContestPlayer's id of rank2 15 | ... 16 | } 17 | """ 18 | id = db.Column(db.Integer, primary_key=True) 19 | ranklist = db.Column(db.Text) 20 | 21 | def __init__(self): 22 | ranklist = {"player_num": 0} 23 | self.ranklist = json.dumps(ranklist) 24 | 25 | def save(self): 26 | db.session.add(self) 27 | db.session.commit() 28 | 29 | def get_players(self): 30 | ranklist = json.loads(self.ranklist) 31 | players = [] 32 | for i in range(ranklist["player_num"]): 33 | player = ContestPlayer.query.filter_by(id=ranklist[str(i)]).first() 34 | players.append(player) 35 | return players 36 | 37 | def update(self, new_player=None): 38 | players = self.get_players() 39 | if not new_player in players: 40 | players.append(new_player) 41 | 42 | players.sort(key = lambda p: p.score, reverse = True) 43 | # players.sort(cmp=lambda x, y: x.score > y.score or (x.score == y.score and x.time_spent < y.time_spent)) 44 | 45 | ranklist = {"player_num": len(players)} 46 | for rank, player in enumerate(players): 47 | ranklist[rank] = player.id 48 | 49 | self.ranklist = json.dumps(ranklist) 50 | 51 | 52 | class ContestPlayer(db.Model): 53 | id = db.Column(db.Integer, primary_key=True) 54 | contest_id = db.Column(db.Integer, db.ForeignKey("contest.id"), index=True) 55 | contest = db.relationship("Contest", backref=db.backref("players", lazy="dynamic")) 56 | user_id = db.Column(db.Integer, db.ForeignKey("user.id"), index=True) 57 | user = db.relationship("User", backref=db.backref("contests", lazy="dynamic")) 58 | 59 | score = db.Column(db.Integer) 60 | score_details = db.Column(db.Text) 61 | time_spent = db.Column(db.Integer) 62 | 63 | def __init__(self, contest_id, user_id): 64 | self.contest_id = contest_id 65 | self.user_id = user_id 66 | 67 | self.score = 0 68 | self.time_spent = 0 69 | self.score_details = "" 70 | 71 | def __repr__(self): 72 | return "" % \ 73 | (self.contest_id, self.user_id, self.score_details) 74 | 75 | def update_score(self, problem, score, judge_id): 76 | score_details = {} 77 | if self.score_details: 78 | score_details = json.loads(self.score_details) 79 | pid = str(problem.id) 80 | score_details[pid] = {} 81 | score_details[pid]["score"] = score 82 | score_details[pid]["judge_id"] = judge_id 83 | score_details["score"] = 0 84 | for key, val in score_details.iteritems(): 85 | if isinstance(val, dict): 86 | score_details["score"] += val["score"] 87 | self.score = score_details["score"] 88 | self.time_spent = problem.submit_num 89 | self.score_details = json.dumps(score_details) 90 | 91 | def get_score_details(self): 92 | return json.loads(self.score_details) 93 | 94 | def save(self): 95 | db.session.add(self) 96 | db.session.commit() 97 | 98 | 99 | class Contest(db.Model): 100 | id = db.Column(db.Integer, primary_key=True) 101 | title = db.Column(db.String(80)) 102 | start_time = db.Column(db.Integer) # goodbye at 2038-1-19 103 | end_time = db.Column(db.Integer) 104 | 105 | holder_id = db.Column(db.Integer, db.ForeignKey("user.id"), index=True) 106 | holder = db.relationship("User", backref=db.backref("hold_contests", lazy='dynamic')) 107 | 108 | information = db.Column(db.Text) 109 | # save use text represent problems id,split by "|" 110 | # for example use "2|23|123" represent this contest use problems which id equal 2\23 or 123 111 | problems = db.Column(db.Text) 112 | 113 | ranklist_id = db.Column(db.Integer, db.ForeignKey("contest_ranklist.id"), index=True) 114 | ranklist = db.relationship("ContestRanklist", backref=db.backref("contests", lazy="dynamic")) 115 | 116 | def __init__(self, title, start_time, end_time, holder): 117 | self.title = title 118 | self.start_time = start_time 119 | self.end_time = end_time 120 | self.holder = holder 121 | 122 | ranklist = ContestRanklist() 123 | self.ranklist = ranklist 124 | 125 | def __repr__(self): 126 | return "" % self.title 127 | 128 | def save(self): 129 | db.session.add(self) 130 | db.session.commit() 131 | 132 | def is_allowed_edit(self, user=None): 133 | if user and user.have_privilege(4): 134 | return True 135 | if user and user.id == self.holder.id: 136 | return True 137 | return False 138 | 139 | def new_submission(self, judge): 140 | problems = self.get_problems() 141 | if judge.problem not in problems: 142 | pass 143 | return False 144 | 145 | player = self.players.filter_by(user_id=judge.user_id).first() 146 | if not player: 147 | player = ContestPlayer(self.id, judge.user_id) 148 | player.update_score(judge.problem, judge.score, judge.id) 149 | player.save() 150 | self.ranklist.update(player) 151 | self.ranklist.save() 152 | 153 | def is_running(self, now=None): 154 | if not now: 155 | now = int(time.time()) 156 | return self.start_time <= now and now <= self.end_time 157 | 158 | def get_ranklist(self): 159 | return self.ranklist.ranklist 160 | 161 | def get_problems(self): 162 | if not self.problems: 163 | return [] 164 | 165 | problems = [] 166 | for pid in self.problems.split('|'): 167 | pid = int(pid) 168 | problems.append(Problem.query.filter_by(id=int(pid)).first()) 169 | return problems 170 | 171 | def set_problems(self, problems_list): 172 | self.problems = "" 173 | for pid in problems_list: 174 | if Problem.query.filter_by(id=pid).first(): 175 | if self.problems: 176 | self.problems += '|' 177 | self.problems += str(pid) 178 | else: 179 | pass 180 | # TODO:raise error 181 | -------------------------------------------------------------------------------- /syzoj/models/file.py: -------------------------------------------------------------------------------- 1 | from syzoj import oj, db 2 | import zipfile, os 3 | import hashlib 4 | 5 | 6 | class File(db.Model): 7 | id = db.Column(db.Integer, primary_key=True) 8 | filename = db.Column(db.String(120), index=True) 9 | md5 = db.Column(db.String(50), index=True) 10 | 11 | def __init__(self, file): 12 | self.file = file 13 | self.md5 = self.calc_md5(file) 14 | 15 | @staticmethod 16 | def calc_md5(file): 17 | file.seek(0) 18 | m = hashlib.md5() 19 | while True: 20 | data = file.read(8192) 21 | if not data: 22 | break 23 | m.update(data) 24 | 25 | md5 = m.hexdigest() 26 | return md5 27 | 28 | def save_file(self): 29 | self.file.seek(0) 30 | self.file.save(os.path.join(oj.config['UPLOAD_FOLDER'], self.md5)) 31 | 32 | def get_file_path(self): 33 | return os.path.join(oj.config["UPLOAD_FOLDER"], self.md5) 34 | 35 | def save(self): 36 | db.session.add(self) 37 | db.session.commit() 38 | 39 | 40 | class FileParser(object): 41 | @staticmethod 42 | def parse_as_testdata(file): 43 | filename = file.get_file_path() 44 | if not zipfile.is_zipfile(filename): 45 | return (False, "This file isn\'t zipfile") 46 | 47 | with zipfile.ZipFile(filename) as zip_file: 48 | file_list = zip_file.namelist() 49 | 50 | if "data_rule.txt" not in file_list: 51 | return (False, "Can\'t find data_rule.txt in testdata pack.") 52 | 53 | data_rule = zip_file.read("data_rule.txt") 54 | 55 | lines = data_rule.split('\n') 56 | for i in range(0, len(lines)): 57 | lines[i] = lines[i].replace('\r', '').replace('\n', '') 58 | 59 | if len(lines) < 3: 60 | return (False, "data_rule.txt should have 3 lines.") 61 | 62 | data_no = lines[0].split() 63 | input_name = lines[1] 64 | output_name = lines[2] 65 | 66 | ret = [] 67 | 68 | for i in data_no: 69 | i = int(i) 70 | input_file = input_name.replace('#', str(i)) 71 | output_file = output_name.replace('#', str(i)) 72 | if input_file not in file_list: 73 | return (False, "Can\'t find %s file." % input_file) 74 | if output_file not in file_list: 75 | return (False, "Can\'t find %s file." % output_file) 76 | ret.append((input_file, output_file)) 77 | 78 | return (True, ret) 79 | -------------------------------------------------------------------------------- /syzoj/models/judge.py: -------------------------------------------------------------------------------- 1 | from syzoj import db 2 | from syzoj.models.contest import Contest 3 | from syzoj.models.user import UserAcProblem 4 | import json 5 | import time 6 | 7 | 8 | class JudgeState(db.Model): 9 | id = db.Column(db.Integer, primary_key=True) 10 | code = db.Column(db.Text) 11 | language = db.Column(db.String(20)) 12 | 13 | status = db.Column(db.String(50), index=True) 14 | score = db.Column(db.Integer, index=True) 15 | result = db.Column(db.Text) 16 | 17 | user_id = db.Column(db.Integer, db.ForeignKey("user.id"), index=True) 18 | user = db.relationship("User", backref=db.backref("submit", lazy='dynamic')) 19 | 20 | problem_id = db.Column(db.Integer, db.ForeignKey("problem.id"), index=True) 21 | problem = db.relationship("Problem", backref=db.backref("submit", lazy='dynamic')) 22 | 23 | submit_time = db.Column(db.Integer) # googbye at 2038-1-19 24 | 25 | # "type" indicate it's contest's submission(type = 1) or normal submission(type = 0) 26 | # type=2: this is a test submission 27 | # if it's contest's submission (type = 1), the type_info is contest_id 28 | # use this way represent because it's easy to expand 29 | type = db.Column(db.Integer) 30 | type_info = db.Column(db.Integer) 31 | 32 | def __init__(self, code, language, user, problem, type=0, type_info=None, submit_time=None): 33 | if not submit_time: 34 | submit_time = int(time.time()) 35 | self.code = code 36 | self.language = language 37 | self.user = user 38 | self.problem = problem 39 | self.submit_time = submit_time 40 | 41 | self.type = type 42 | self.type_info = type_info 43 | 44 | self.score = 0 45 | self.status = "Waiting" 46 | self.result = '{"status": "Waiting", "total_time": 0, "total_memory": 0, "score":0, "case_num": 0}' 47 | 48 | def __repr__(self): 49 | print "" % self.id 50 | 51 | def save(self): 52 | db.session.add(self) 53 | db.session.commit() 54 | 55 | def is_allowed_see_result(self, user=None): 56 | if user and user.id == self.problem.user.id: 57 | return True 58 | 59 | if self.type == 0: 60 | if not self.problem.is_public: 61 | if user and (user.have_privilege(2) or user.have_privilege(3)): 62 | return True 63 | return False 64 | return True 65 | elif self.type == 1: 66 | if user and user.have_privilege(4): 67 | return True 68 | contest = Contest.query.filter_by(id=self.type_info).first() 69 | if contest.is_running(): 70 | return False 71 | else: 72 | return True 73 | elif self.type == 2: 74 | if user and (user.have_privilege(2) or user.have_privilege(3) or self.user == user.id): 75 | return True 76 | else: 77 | return False 78 | 79 | return False 80 | 81 | def is_allowed_see_code(self, user=None): 82 | if user and user.id == self.problem.user.id: 83 | return True 84 | 85 | if self.type == 0: 86 | if not self.problem.is_public: 87 | if user and (user.have_privilege(2) or user.have_privilege(3)): 88 | return True 89 | return False 90 | return True 91 | elif self.type == 1: 92 | if user and user.have_privilege(4): 93 | return True 94 | contest = Contest.query.filter_by(id=self.type_info).first() 95 | if contest.is_running(): 96 | if user and self.user == user: 97 | return True 98 | else: 99 | return False 100 | else: 101 | return True 102 | elif self.type == 2: 103 | if user and (user.have_privilege(2) or user.have_privilege(3) or self.user == user.id): 104 | return True 105 | else: 106 | return False 107 | 108 | return False 109 | 110 | def get_result(self): 111 | return json.loads(self.result) 112 | 113 | def update_result(self, result): 114 | self.score = result["score"] 115 | self.status = result["status"] 116 | self.result = json.dumps(result) 117 | 118 | def update_related_info(self): 119 | if self.type == 0: 120 | self.user.refresh_submit_info() 121 | self.user.save() 122 | 123 | self.problem.submit_num += 1 124 | if self.status == "Accepted": 125 | self.problem.ac_num += 1 126 | self.problem.save() 127 | elif self.type == 1: 128 | contest = Contest.query.filter_by(id=self.type_info).first() 129 | contest.new_submission(self) 130 | 131 | # only normal submittion is counted 132 | def update_userac_info(self): 133 | if self.type == 0: 134 | all_user_ac = UserAcProblem.query.filter_by(user_id = self.user.id).all() 135 | for ac_info in all_user_ac: 136 | if ac_info.problem_id == self.problem.id: 137 | if ac_info.is_accepted and self.status != "Accepted": 138 | return 139 | 140 | new_ac_info = UserAcProblem(user_id = ac_info.user_id, problem_id = ac_info.problem_id, judge_id = self.id) 141 | ac_info.delete() 142 | 143 | if self.status == "Accepted": 144 | new_ac_info.is_accepted = True 145 | else: 146 | new_ac_info.is_accepted = False 147 | new_ac_info.save() 148 | return 149 | 150 | new_ac_info = UserAcProblem(user_id = self.user.id, problem_id = self.problem.id, judge_id = self.id) 151 | if self.status == "Accepted": 152 | new_ac_info.is_accepted = True 153 | else: 154 | new_ac_info.is_accepted = False 155 | new_ac_info.save() 156 | return 157 | 158 | 159 | class WaitingJudge(db.Model): 160 | id = db.Column(db.Integer, primary_key=True) 161 | judge_id = db.Column(db.Integer, db.ForeignKey("judge_state.id")) 162 | judge = db.relationship("JudgeState", backref=db.backref("waiting_judge", lazy="dynamic")) 163 | 164 | def __init__(self, judge): 165 | self.judge = judge 166 | 167 | def __repr__(self): 168 | print "" % self.judge_id 169 | 170 | def save(self): 171 | db.session.add(self) 172 | db.session.commit() 173 | 174 | def delete(self): 175 | db.session.delete(self) 176 | db.session.commit() 177 | -------------------------------------------------------------------------------- /syzoj/models/problem.py: -------------------------------------------------------------------------------- 1 | from syzoj import db 2 | from syzoj.models.file import File 3 | 4 | tags_table = db.Table('problem_tags', 5 | db.Column('tag_id', db.Integer, db.ForeignKey('problem_tag.id'), index=True), 6 | db.Column('problem_id', db.Integer, db.ForeignKey('problem.id'), index=True) 7 | ) 8 | 9 | 10 | class Problem(db.Model): 11 | id = db.Column(db.Integer, primary_key=True) 12 | 13 | title = db.Column(db.String(80), index=True) 14 | user_id = db.Column(db.Integer, db.ForeignKey("user.id"), index=True) 15 | user = db.relationship("User", backref=db.backref("upload_problems", lazy='dynamic')) 16 | 17 | description = db.Column(db.Text) 18 | input_format = db.Column(db.Text) 19 | output_format = db.Column(db.Text) 20 | example = db.Column(db.Text) 21 | limit_and_hint = db.Column(db.Text) 22 | 23 | time_limit = db.Column(db.Integer) 24 | memory_limit = db.Column(db.Integer) 25 | 26 | testdata_id = db.Column(db.Integer, db.ForeignKey("file.id")) 27 | testdata = db.relationship("File", backref=db.backref('problems', lazy='dynamic')) 28 | 29 | tags = db.relationship('ProblemTag', secondary=tags_table, 30 | backref=db.backref('problems', lazy='dynamic')) 31 | 32 | ac_num = db.Column(db.Integer) 33 | submit_num = db.Column(db.Integer) 34 | is_public = db.Column(db.Boolean) 35 | 36 | def __init__(self, title, user, 37 | description="", input_format="", output_format="", example="", limit_and_hint="", 38 | time_limit=1000, memory_limit=128 39 | ): 40 | self.title = title 41 | self.user = user 42 | 43 | self.description = description 44 | self.input_format = input_format 45 | self.output_format = output_format 46 | self.example = example 47 | self.limit_and_hint = limit_and_hint 48 | 49 | self.time_limit = time_limit 50 | self.memory_limit = memory_limit 51 | 52 | self.ac_num = 0 53 | self.submit_num = 0 54 | self.is_public = False 55 | 56 | def __repr__(self): 57 | return "" % self.title 58 | 59 | def save(self): 60 | db.session.add(self) 61 | db.session.commit() 62 | 63 | def update(self, title=None, description=None, input_format=None, output_format=None, example=None, 64 | limit_and_hint=None): 65 | self.title = title 66 | self.description = description 67 | self.input_format = input_format 68 | self.output_format = output_format 69 | self.example = example 70 | self.limit_and_hint = limit_and_hint 71 | 72 | def update_testdata(self, file): 73 | self.testdata = File(file) 74 | self.testdata.filename = "test_data_%d.zip" % self.id 75 | self.testdata.save_file() 76 | self.testdata.save() 77 | 78 | def is_allowed_edit(self, user=None): 79 | if not user: 80 | return False 81 | if self.user_id == user.id or user.have_privilege(2): 82 | return True 83 | return False 84 | 85 | def is_allowed_use(self, user=None): 86 | if self.is_public: 87 | return True 88 | if not user: 89 | return False 90 | if self.user_id == user.id or user.have_privilege(3) or user.have_privilege(2): 91 | return True 92 | return False 93 | 94 | def set_is_public(self, public): 95 | self.is_public = public 96 | self.save() 97 | 98 | 99 | class ProblemTag(db.Model): 100 | id = db.Column(db.Integer, primary_key=True) 101 | name = db.Column(db.String(80), index=True) 102 | 103 | def __init__(self, name): 104 | self.name = name 105 | 106 | def __repr__(self): 107 | return "" % self.name 108 | 109 | def save(self): 110 | db.session.add(self) 111 | db.session.commit() 112 | -------------------------------------------------------------------------------- /syzoj/models/user.py: -------------------------------------------------------------------------------- 1 | from flask import request 2 | from syzoj import db 3 | from .problem import Problem 4 | import urllib, hashlib 5 | from random import randint 6 | import time 7 | 8 | 9 | class Session(db.Model): 10 | id = db.Column(db.String(120), primary_key=True) 11 | 12 | user_id = db.Column(db.Integer, db.ForeignKey("user.id"), index=True) 13 | user = db.relationship("User", backref=db.backref("sessions", lazy='dynamic')) 14 | 15 | login_time = db.Column(db.Integer) # googbye at 2038-1-19 16 | expiration_time = db.Column(db.Integer) 17 | 18 | def __init__(self, user, login_time=None, valid_time=3600 * 24 * 7): 19 | if not login_time: 20 | login_time = int(time.time()) 21 | self.id = str(randint(1, int(1e50))) 22 | self.user = user 23 | self.login_time = login_time 24 | self.expiration_time = login_time + valid_time 25 | 26 | def __repr__(self): 27 | print "" % (self.username, self.password, self.email) 108 | 109 | def save(self): 110 | db.session.add(self) 111 | db.session.commit() 112 | 113 | def have_privilege(self, privilege_type): 114 | for privilege in UserPrivilege.query.filter_by(user_id = self.id).all(): 115 | if privilege.privilege_type == privilege_type or privilege.privilege_type == 1: 116 | return True 117 | return False 118 | 119 | def is_allowed_edit(self, user): 120 | if not user: 121 | return False 122 | if self.id == user.id or user.have_privilege(7): 123 | return True 124 | return False 125 | 126 | def get_submitted_problems(self): 127 | submitted_problems = dict() 128 | for ac_info in UserAcProblem.query.filter_by(user_id = self.id).all(): 129 | submitted_problems[ac_info.problem_id] = [ac_info.is_accepted, ac_info.judge_id] 130 | return submitted_problems 131 | 132 | def refresh_submit_info(self): 133 | cnt = 0 134 | for ac_info in UserAcProblem.query.filter_by(user_id = self.id).all(): 135 | if ac_info.is_accepted: 136 | cnt += 1 137 | self.ac_num = cnt 138 | 139 | @staticmethod 140 | def get_cur_user(session_id=None): 141 | if not session_id: 142 | session_id = request.cookies.get('session_id') 143 | 144 | sessions = Session.query.filter_by(id=session_id).all() 145 | for s in sessions: 146 | if s.is_valid(): 147 | return s.user 148 | 149 | return None 150 | 151 | @staticmethod 152 | def find_user(nickname=None, id=None): 153 | if id: 154 | return User.query.filter_by(id=id).first() 155 | 156 | if nickname: 157 | return User.query.filter_by(nickname=nickname).first() 158 | 159 | return None 160 | 161 | def give_privilege(self, privilege_type): 162 | for privilege in UserPrivilege.query.filter_by(user_id = self.id).all(): 163 | if privilege.privilege_type == privilege_type: 164 | return False # User already had privilege 165 | new_privilege = UserPrivilege(user_id = self.id, privilege_type = privilege_type) 166 | new_privilege.save() 167 | return True 168 | 169 | def del_privilege(self, privilege_type): 170 | for privilege in UserPrivilege.query.filter_by(user_id = self.id).all(): 171 | if privilege.privilege_type == privilege_type: 172 | privilege.delete() 173 | return True 174 | return False # User doesnt have privilege 175 | 176 | class UserAcProblem(db.Model): 177 | __tablename__ = 'UserAcProblem' 178 | id = db.Column(db.Integer, primary_key = True) 179 | user_id = db.Column(db.Integer, index = True) 180 | problem_id = db.Column(db.Integer) 181 | is_accepted = db.Column(db.BOOLEAN) 182 | judge_id = db.Column(db.Integer) 183 | 184 | def __init__(self, user_id, problem_id, judge_id): 185 | self.user_id = user_id 186 | self.problem_id = problem_id 187 | self.is_accepted = False 188 | self.judge_id = judge_id 189 | 190 | def save(self): 191 | db.session.add(self) 192 | db.session.commit() 193 | 194 | def delete(self): 195 | db.session.delete(self) 196 | db.session.commit() 197 | 198 | 199 | 200 | -------------------------------------------------------------------------------- /syzoj/static/auto-render.js: -------------------------------------------------------------------------------- 1 | var findEndOfMath=function(delimiter,text,startIndex){var index=startIndex;var braceLevel=0;var delimLength=delimiter.length;while(index>>(32-o))};var a=function(s,p){var u,o,r,t,q;r=(s&2147483648);t=(p&2147483648);u=(s&1073741824);o=(p&1073741824);q=(s&1073741823)+(p&1073741823);if(u&o){return(q^2147483648^r^t)}if(u|o){if(q&1073741824){return(q^3221225472^r^t)}else{return(q^1073741824^r^t)}}else{return(q^r^t)}};var n=function(o,q,p){return(o&q)|((~o)&p)};var l=function(o,q,p){return(o&p)|(q&(~p))};var j=function(o,q,p){return(o^q^p)};var i=function(o,q,p){return(q^(o|(~p)))};var g=function(q,p,v,u,o,r,t){q=a(q,a(a(n(p,v,u),o),t));return a(m(q,r),p)};var c=function(q,p,v,u,o,r,t){q=a(q,a(a(l(p,v,u),o),t));return a(m(q,r),p)};var h=function(q,p,v,u,o,r,t){q=a(q,a(a(j(p,v,u),o),t));return a(m(q,r),p)};var d=function(q,p,v,u,o,r,t){q=a(q,a(a(i(p,v,u),o),t));return a(m(q,r),p)};var f=function(r){var v;var q=r.length;var p=q+8;var u=(p-(p%64))/64;var t=(u+1)*16;var w=Array(t-1);var o=0;var s=0;while(s>>29;return w};var b=function(r){var q="",o="",s,p;for(p=0;p<=3;p++){s=(r>>>(p*8))&255;o="0"+s.toString(16);q=q+o.substr(o.length-2,2)}return q};var k=function(p){p=p.replace(/\x0d\x0a/g,"\x0a");var o="";for(var r=0;r127)&&(q<2048)){o+=String.fromCharCode((q>>6)|192);o+=String.fromCharCode((q&63)|128)}else{o+=String.fromCharCode((q>>12)|224);o+=String.fromCharCode(((q>>6)&63)|128);o+=String.fromCharCode((q&63)|128)}}}return o};e.extend({md5:function(o){var v=Array();var G,H,p,u,F,Q,P,N,K;var D=7,B=12,z=17,w=22;var O=5,L=9,J=14,I=20;var t=4,s=11,r=16,q=23;var E=6,C=10,A=15,y=21;o=k(o);v=f(o);Q=1732584193;P=4023233417;N=2562383102;K=271733878;for(G=0;G[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:l,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};d.bullet=/(?:[*+-]|\d+\.)/;d.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;d.item=c(d.item,"gm")(/bull/g,d.bullet)();d.list=c(d.list)(/bull/g,d.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+d.def.source+")")();d.blockquote=c(d.blockquote)("def",d.def)();d._tag="(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";d.html=c(d.html)("comment",//)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,d._tag)();d.paragraph=c(d.paragraph)("hr",d.hr)("heading",d.heading)("lheading",d.lheading)("blockquote",d.blockquote)("tag","<"+d._tag)("def",d.def)();d.normal=i({},d);d.gfm=i({},d.normal,{fences:/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/});d.gfm.paragraph=c(d.paragraph)("(?!","(?!"+d.gfm.fences.source.replace("\\1","\\2")+"|"+d.list.source.replace("\\1","\\3")+"|")();d.tables=i({},d.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function b(m){this.tokens=[];this.tokens.links={};this.options=m||a.defaults;this.rules=d.normal;if(this.options.gfm){if(this.options.tables){this.rules=d.tables}else{this.rules=d.gfm}}}b.rules=d;b.lex=function(o,m){var n=new b(m);return n.lex(o)};b.prototype.lex=function(m){m=m.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(m,true)};b.prototype.token=function(n,t,x){var n=n.replace(/^ +$/gm,""),r,p,v,s,u,w,m,q,o;while(n){if(v=this.rules.newline.exec(n)){n=n.substring(v[0].length);if(v[0].length>1){this.tokens.push({type:"space"})}}if(v=this.rules.code.exec(n)){n=n.substring(v[0].length);v=v[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?v.replace(/\n+$/,""):v});continue}if(v=this.rules.fences.exec(n)){n=n.substring(v[0].length);this.tokens.push({type:"code",lang:v[2],text:v[3]});continue}if(v=this.rules.heading.exec(n)){n=n.substring(v[0].length);this.tokens.push({type:"heading",depth:v[1].length,text:v[2]});continue}if(t&&(v=this.rules.nptable.exec(n))){n=n.substring(v[0].length);w={type:"table",header:v[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:v[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:v[3].replace(/\n$/,"").split("\n")};for(q=0;q ?/gm,"");this.token(v,t,true);this.tokens.push({type:"blockquote_end"});continue}if(v=this.rules.list.exec(n)){n=n.substring(v[0].length);s=v[2];this.tokens.push({type:"list_start",ordered:s.length>1});v=v[0].match(this.rules.item);r=false;o=v.length;q=0;for(;q1&&u.length>1)){n=v.slice(q+1).join("\n")+n;q=o-1}}p=r||/\n\n(?!\s*$)/.test(w);if(q!==o-1){r=w.charAt(w.length-1)==="\n";if(!p){p=r}}this.tokens.push({type:p?"loose_item_start":"list_item_start"});this.token(w,false,x);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(v=this.rules.html.exec(n)){n=n.substring(v[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:v[1]==="pre"||v[1]==="script"||v[1]==="style",text:v[0]});continue}if((!x&&t)&&(v=this.rules.def.exec(n))){n=n.substring(v[0].length);this.tokens.links[v[1].toLowerCase()]={href:v[2],title:v[3]};continue}if(t&&(v=this.rules.table.exec(n))){n=n.substring(v[0].length);w={type:"table",header:v[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:v[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:v[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(q=0;q])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:l,tag:/^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:l,text:/^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/;h.link=c(h.link)("inside",h._inside)("href",h._href)();h.reflink=c(h.reflink)("inside",h._inside)();h.normal=i({},h);h.pedantic=i({},h.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});h.gfm=i({},h.normal,{escape:c(h.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:c(h.text)("]|","~]|")("|","|https?://|")()});h.breaks=i({},h.gfm,{br:c(h.br)("{2,}","*")(),text:c(h.gfm.text)("{2,}","*")()});function j(m,n){this.options=n||a.defaults;this.links=m;this.rules=h.normal;this.renderer=this.options.renderer||new f;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=h.breaks}else{this.rules=h.gfm}}else{if(this.options.pedantic){this.rules=h.pedantic}}}j.rules=h;j.output=function(p,m,n){var o=new j(m,n);return o.output(p)};j.prototype.output=function(r){var n="",p,q,m,o;while(r){if(o=this.rules.escape.exec(r)){r=r.substring(o[0].length);n+=o[1];continue}if(o=this.rules.autolink.exec(r)){r=r.substring(o[0].length);if(o[2]==="@"){q=o[1].charAt(6)===":"?this.mangle(o[1].substring(7)):this.mangle(o[1]);m=this.mangle("mailto:")+q}else{q=k(o[1]);m=q}n+=this.renderer.link(m,null,q);continue}if(!this.inLink&&(o=this.rules.url.exec(r))){r=r.substring(o[0].length);q=k(o[1]);m=q;n+=this.renderer.link(m,null,q);continue}if(o=this.rules.tag.exec(r)){if(!this.inLink&&/^/i.test(o[0])){this.inLink=false}}r=r.substring(o[0].length);n+=this.options.sanitize?k(o[0]):o[0];continue}if(o=this.rules.link.exec(r)){r=r.substring(o[0].length);this.inLink=true;n+=this.outputLink(o,{href:o[2],title:o[3]});this.inLink=false;continue}if((o=this.rules.reflink.exec(r))||(o=this.rules.nolink.exec(r))){r=r.substring(o[0].length);p=(o[2]||o[1]).replace(/\s+/g," ");p=this.links[p.toLowerCase()];if(!p||!p.href){n+=o[0].charAt(0);r=o[0].substring(1)+r;continue}this.inLink=true;n+=this.outputLink(o,p);this.inLink=false;continue}if(o=this.rules.strong.exec(r)){r=r.substring(o[0].length);n+=this.renderer.strong(this.output(o[2]||o[1]));continue}if(o=this.rules.em.exec(r)){r=r.substring(o[0].length);n+=this.renderer.em(this.output(o[2]||o[1]));continue}if(o=this.rules.code.exec(r)){r=r.substring(o[0].length);n+=this.renderer.codespan(k(o[2],true));continue}if(o=this.rules.br.exec(r)){r=r.substring(o[0].length);n+=this.renderer.br();continue}if(o=this.rules.del.exec(r)){r=r.substring(o[0].length);n+=this.renderer.del(this.output(o[1]));continue}if(o=this.rules.text.exec(r)){r=r.substring(o[0].length);n+=k(this.smartypants(o[0]));continue}if(r){throw new Error("Infinite loop on byte: "+r.charCodeAt(0))}}return n};j.prototype.outputLink=function(n,o){var m=k(o.href),p=o.title?k(o.title):null;return n[0].charAt(0)!=="!"?this.renderer.link(m,p,this.output(n[1])):this.renderer.image(m,p,k(n[1]))};j.prototype.smartypants=function(m){if(!this.options.smartypants){return m}return m.replace(/--/g,"\u2014").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1\u2018").replace(/'/g,"\u2019").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1\u201c").replace(/"/g,"\u201d").replace(/\.{3}/g,"\u2026")};j.prototype.mangle=function(q){var n="",m=q.length,o=0,p;for(;o0.5){p="x"+p.toString(16)}n+="&#"+p+";"}return n};function f(m){this.options=m||{}}f.prototype.code=function(n,p,o){if(this.options.highlight){var m=this.options.highlight(n,p);if(m!=null&&m!==n){o=true;n=m}}if(!p){return"
    "+(o?n:k(n,true))+"\n
    "}return'
    '+(o?n:k(n,true))+"\n
    \n"};f.prototype.blockquote=function(m){return"
    \n"+m+"
    \n"};f.prototype.html=function(m){return m};f.prototype.heading=function(n,o,m){return"'+n+"\n"};f.prototype.hr=function(){return this.options.xhtml?"
    \n":"
    \n"};f.prototype.list=function(m,n){var o=n?"ol":"ul";return"<"+o+">\n"+m+"\n"};f.prototype.listitem=function(m){return"
  • "+m+"
  • \n"};f.prototype.paragraph=function(m){return"

    "+m+"

    \n"};f.prototype.table=function(n,m){return"\n\n"+n+"\n\n"+m+"\n
    \n"};f.prototype.tablerow=function(m){return"\n"+m+"\n"};f.prototype.tablecell=function(p,n){var o=n.header?"th":"td";var m=n.align?"<"+o+' style="text-align:'+n.align+'">':"<"+o+">";return m+p+"\n"};f.prototype.strong=function(m){return""+m+""};f.prototype.em=function(m){return""+m+""};f.prototype.codespan=function(m){return""+m+""};f.prototype.br=function(){return this.options.xhtml?"
    ":"
    "};f.prototype.del=function(m){return""+m+""};f.prototype.link=function(m,r,q){if(this.options.sanitize){try{var o=decodeURIComponent(g(m)).replace(/[^\w:]/g,"").toLowerCase()}catch(p){return""}if(o.indexOf("javascript:")===0||o.indexOf("vbscript:")===0){return""}}var n='
    ";return n};f.prototype.image=function(m,p,o){var n=''+o+'":">";return n};function e(m){this.tokens=[];this.token=null;this.options=m||a.defaults;this.options.renderer=this.options.renderer||new f;this.renderer=this.options.renderer;this.renderer.options=this.options}e.parse=function(o,m,n){var p=new e(m,n);return p.parse(o)};e.prototype.parse=function(n){this.inline=new j(n.links,this.options,this.renderer);this.tokens=n.reverse();var m="";while(this.next()){m+=this.tok()}return m};e.prototype.next=function(){return this.token=this.tokens.pop()};e.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};e.prototype.parseText=function(){var m=this.token.text;while(this.peek().type==="text"){m+="\n"+this.next().text}return this.inline.output(m)};e.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var q="",s="",o,u,t,m,n;t="";for(o=0;o/g,">").replace(/"/g,""").replace(/'/g,"'")}function g(m){return m.replace(/&([#\w]+);/g,function(o,p){p=p.toLowerCase();if(p==="colon"){return":"}if(p.charAt(0)==="#"){return p.charAt(1)==="x"?String.fromCharCode(parseInt(p.substring(2),16)):String.fromCharCode(+p.substring(1))}return""})}function c(o,n){o=o.source;n=n||"";return function m(p,q){if(!p){return new RegExp(o,n)}q=q.source||q;q=q.replace(/(^|[^\[])\^/g,"$1");o=o.replace(p,q);return m}}function l(){}l.exec=l;function i(p){var n=1,o,m;for(;nAn error occured:

    "+k(s.message+"",true)+"
    "}throw s}}a.options=a.setOptions=function(m){i(a.defaults,m);return a};a.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new f,xhtml:false};a.Parser=e;a.parser=e.parse;a.Renderer=f;a.Lexer=b;a.lexer=b.lex;a.InlineLexer=j;a.inlineLexer=j.output;a.parse=a;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=a}else{if(typeof define==="function"&&define.amd){define(function(){return a})}else{this.marked=a}}}).call(function(){return this||(typeof window!=="undefined"?window:global)}()); 2 | -------------------------------------------------------------------------------- /syzoj/static/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} -------------------------------------------------------------------------------- /syzoj/static/prettify.js: -------------------------------------------------------------------------------- 1 | !function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; 2 | (function(){function S(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:"0"<=a&&a<="7"?parseInt(e.substring(1),8):a==="u"||a==="x"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return e==="\\"||e==="-"||e==="]"||e==="^"?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),e=[],a= 3 | b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,f=b.length;a122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;ah[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(g(h[1])));c.push("]");return c.join("")}function s(e){for(var a=e.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],f=0,h=0;f=2&&e==="["?a[f]=b(l):e!=="\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k=5&&"lang-"===w.substring(0,5))&&!(t&&typeof t[1]==="string"))f=!1,w="src";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c=0;)b[n.charAt(e)]=r;r=r[1];n=""+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\S\s]/);s=S(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, 10 | q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&g.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),g.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,q])):d.push(["com", 11 | /^#[^\n\r]*/,q,"#"]));a.cStyleComments&&(g.push(["com",/^\/\/[^\n\r]*/,q]),g.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?"":"\n\r")?".":"[\\S\\s]";g.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+s+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+ 12 | s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/, 13 | q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d= 14 | c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], 18 | "catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"], 19 | O=[N,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],E=[E,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],P=[y,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], 20 | Q=[y,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],W=[y,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],y=[y,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],R=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/, 21 | V=/\S/,X=v({keywords:[M,O,E,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",P,Q,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,["default-code"]);p(C([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-", 22 | /^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);p(C([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/], 23 | ["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);p(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);p(v({keywords:M,hashComments:!0,cStyleComments:!0,types:R}),["c","cc","cpp","cxx","cyc","m"]);p(v({keywords:"null,true,false"}),["json"]);p(v({keywords:O,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:R}), 24 | ["cs"]);p(v({keywords:N,cStyleComments:!0}),["java"]);p(v({keywords:y,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(v({keywords:P,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(v({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);p(v({keywords:Q, 25 | hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(v({keywords:E,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(v({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(v({keywords:W,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]); 26 | p(C([],[["str",/^[\S\s]+/]]),["regex"]);var Y=D.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:v,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:D.prettyPrintOne=function(a,d,g){var b=document.createElement("div");b.innerHTML="
    "+a+"
    ";b=b.firstChild;g&&J(b,g,!0);K({h:d,j:g,c:b,i:1}); 27 | return b.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function g(){for(var b=D.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;i 5 | .small{ 6 | font-size: 0.7em; 7 | } 8 | 9 |
    10 |
    11 |

    {{article.title}}

    12 |

    13 | {{article.user.nickname}} 14 | {% if article.user.nameplate %}{{article.user.nameplate|safe}}{% endif %} 于{{tool.pretty_time(article.public_time)}}发表,{{tool.pretty_time(article.update_time)}}最后更新 15 | {% if article.is_allowed_edit(user) %} 16 | 删除文章 17 | 编辑文章 18 | {% endif %} 19 |

    20 |
    21 |
    22 |
    23 |
    {{article.content}}
    24 |
    25 |
    26 |
    27 |

    共{{ comment_num }}条回复

    28 | {% set comments = sorter.get() %} 29 | {% for comment in comments %} 30 |
    31 |
    32 |
    33 |

    34 | {{ tool.pretty_time(comment.public_time) }} 35 |

    36 | 37 |

    {{comment.user.nickname}}

    38 |
    39 |
    {{ comment.content }}
    40 |
    41 |
    42 | {% endfor %} 43 | {{ sorter.get_html() | safe }} 44 |
    45 |
    46 |
    47 |
    48 |
    49 | 50 |
    51 | 52 |
    53 |
    54 |
    55 | {% endblock %} 56 | 57 | {% block script %} 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 81 | {% endblock %} -------------------------------------------------------------------------------- /syzoj/templates/contest.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block contest_tab %} am-active {% endblock %} 3 | {% block body %} 4 |
    5 |

    {{ contest.title }}

    6 | 7 |
    8 | {% if contest.is_allowed_edit(user) or not contest.is_running() %} 9 | 排行榜 11 | {% endif %} 12 | {% if contest.is_allowed_edit(user) %} 13 | 编辑比赛 14 | {% endif %} 15 |
    16 |
    17 |
    18 |
    19 | {{ contest.information }} 20 |
    21 |
    22 |
    23 |
    24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | {% set problems = contest.get_problems() %} 32 | {% set i = 0 %} 33 | {% for problem in problems %} 34 | 35 | 36 | 37 | 39 | 40 | 41 | {% set i = i+1 %} 42 | {% endfor %} 43 |
    提交状态题目
    {{ info[problem.id] | safe}}{{ problem.title 38 | }}
    44 |
    45 |
    46 | {% endblock %} 47 | -------------------------------------------------------------------------------- /syzoj/templates/contest_list.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block contest_tab %} am-active {% endblock %} 3 | {% block body %} 4 |
    5 |

    比赛列表

    6 | 7 |
    8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {% set contests = sorter.get() %} 19 | {% for contest in contests %} 20 | 21 | {% if now < contest.start_time %} 22 | {% set tag = '未开始' %} 23 | {% elif contest.is_running() %} 24 | {% set tag = '进行中' %} 25 | {% else %} 26 | {% set tag = '已结束' %} 27 | {% endif %} 28 | 29 | 30 | 31 | 32 | 33 | 34 | {% endfor %} 35 | 36 |
    比赛名称
    开始时间
    结束时间
    比赛介绍
    {{contest.title}}{{ tool.pretty_time(contest.start_time) }}{{ tag|safe }} {{ tool.pretty_time(contest.end_time) }}{{ contest.information }}
    37 |
    38 |
    39 | {{sorter.get_html()|safe}} 40 |
    41 | {% endblock %} 42 | -------------------------------------------------------------------------------- /syzoj/templates/contest_problem.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block contest_tab %}am-active{% endblock %} 3 | {% block body %} 4 | 12 |
    13 |
    14 |

    {{ contest.title }} - {{ problem.title }}

    15 | 16 |

    17 | 内存限制: {{problem.memory_limit}} MB 18 | 时间限制: {{problem.time_limit}} ms 19 |

    20 |
    21 |
    22 |
    23 | 24 |

    题目描述

    25 |
    {{problem.description}}
    26 | 27 |

    输入格式

    28 |
    {{problem.input_format}}
    29 | 30 |

    输出格式

    31 |
    {{problem.output_format}}
    32 | 33 |

    测试样例

    34 |
    {{problem.example}}
    35 | 36 |

    数据范围与提示

    37 |
    {{problem.limit_and_hint}}
    38 |
    39 |
    40 |
    41 |

    提交代码

    42 | 43 |
    45 |
    46 | 47 | 50 | 51 |
    52 |
    53 | 54 | 55 |
    56 | 57 |
    58 |
    59 |
    60 | {% endblock %} 61 | {% block script %} 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 91 | {% endblock %} 92 | -------------------------------------------------------------------------------- /syzoj/templates/contest_ranklist.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block contest_tab %}am-active{% endblock %} 3 | {% block body %} 4 |
    5 |

    {{ contest.title }}排名

    6 | 7 |
    8 | 9 | 10 | 11 | 12 | 13 | {% set problems = contest.get_problems() %} 14 | {% set i = 0 %} 15 | {% for problem in problems %} 16 | 18 | {% set i = i + 1 %} 19 | {% endfor %} 20 | 21 | 22 | 23 | 24 | {% set players = contest.ranklist.get_players() %} 25 | {% set i = 1 %} 26 | {% for player in players%} 27 | {% set user = player.user %} 28 | {% set score_details = player.get_score_details() %} 29 | 30 | 31 | 34 | {% for problem in problems %} 35 | {% set pid = tool.to_str(problem.id) %} 36 | {% if pid in score_details %} 37 | 39 | {% else %} 40 | 41 | {% endif %} 42 | {% endfor %} 43 | 44 | 45 | {% set i = i + 1 %} 46 | {% endfor %} 47 | 48 |
    #
    用户昵称
    {{ problem.title 17 | }}
    总分
    {{ i }}{{ user.nickname }}{% if user.nameplate 32 | %}{{user.nameplate|safe}}{% endif %} 33 | {{ 38 | score_details[pid]['score'] }}{{ player.score }}
    49 |
    50 |
    51 | {%endblock%} 52 | -------------------------------------------------------------------------------- /syzoj/templates/delete_article.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
    4 |

    你真的要删除文章 {{article.title}} 吗?该操作目前不可逆,请谨慎操作

    5 | 我知道我在干什么,删除 6 |
    7 | {% endblock %} -------------------------------------------------------------------------------- /syzoj/templates/discussion.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
    4 |

    讨论区

    5 |
    6 | 发表文章 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {% set articles = sorter.get() %} 17 | {% for article in articles %} 18 | 19 | 20 | 21 | 22 | 23 | {% endfor %} 24 | 25 |
    标题
    作者
    发表时间
    {{article.title}}
    {{article.user.nickname}}
    {{tool.pretty_time(article.public_time)}}
    26 |
    27 | 28 | {{sorter.get_html()|safe}} 29 |
    30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /syzoj/templates/edit_article.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 | 8 |
    9 | {% if article %} 10 | {% set article_id=article.id %} 11 |

    更新文章

    12 | {% else %} 13 | {% set article_id=0 %} 14 |

    发表文章

    15 | {% endif %} 16 |
    17 |
    18 | 26 |
    27 |
    28 |
    29 |
    30 | 31 | 33 |
    34 | 35 |
    36 | 37 | 38 |
    39 |
    40 |
    41 | 42 |
    43 |

    44 |
    45 |
    46 |
    47 |
    48 | 49 |
    50 |
    51 | {% endblock %} 52 | 53 | {% block script %} 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 72 | {% endblock %} 73 | -------------------------------------------------------------------------------- /syzoj/templates/edit_contest.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block contest_tab %}am-active{% endblock %} 3 | {% block body %} 4 |
    5 | {% if contest %} 6 |

    修改 {{ contest.title }}

    7 | {% set contest_id = contest.id %} 8 | {% else %} 9 |

    新建比赛

    10 | {% set contest_id = 0 %} 11 | {% endif %} 12 |
    13 |
    14 |
    15 | 16 | 17 |
    18 |
    19 | 20 | 22 |
    23 |
    24 | 25 | 26 |
    27 |
    28 | 29 | 30 |
    31 |
    32 | 33 | 34 |
    35 | 36 |
    37 | 38 |
    39 | {% endblock %} -------------------------------------------------------------------------------- /syzoj/templates/edit_problem.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 | 11 |
    12 | {% if problem %} 13 | {% set problem_id=problem.id %} 14 |

    修改题目

    15 | {% else %} 16 | {% set problem_id=0 %} 17 |

    上传题目

    18 | {% endif %} 19 |
    20 |
    21 | 29 |
    30 |
    31 |
    32 |
    33 | 34 | 36 |
    37 | 38 |
    39 | 40 | 41 |
    42 | 43 |
    44 | 45 | 46 |
    47 | 48 |
    49 | 50 | 51 |
    52 | 53 |
    54 | 55 | 56 |
    57 | 58 |
    59 | 60 | 61 |
    62 |
    63 |
    64 | 65 |
    66 |

    67 | 68 |

    题目描述

    69 |
    70 |

    输入格式

    71 |
    72 |

    输出格式

    73 |
    74 |

    测试样例

    75 |
    76 |

    数据范围与提示

    77 |
    78 |
    79 |
    80 |
    81 | 82 |
    83 |
    84 | {% endblock %} 85 | 86 | {% block script %} 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 109 | {% endblock %} 110 | -------------------------------------------------------------------------------- /syzoj/templates/edit_user.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
    4 |
    5 |

    修改资料

    6 |
    8 | {% if status==1 %} 9 |

    修改成功

    10 | {% elif status==3001 %} 11 |

    邮箱格式错误

    12 | {% elif status==3002 %} 13 |

    原密码错误...不要偷偷改别人密码哦

    14 | {% elif status==3003%} 15 |

    新密码不得为空

    16 | {% else %} 17 |

    未知状态

    18 | {% endif %} 19 |
    20 |
    21 |
    22 | 23 |
    24 | 25 |
    26 |
    27 |
    28 | 29 |
    30 | 31 |
    32 |
    33 |
    34 | 35 |
    36 |
    37 | 38 | 39 | 40 |
    41 |
    42 |
    43 | {% if user and not user.have_privilege(1) %} 44 |
    45 | {% endif %} 46 |
    47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
    56 | {% if user and not user.have_privilege(1) %} 57 |
    58 | {% endif %} 59 |
    60 |
    61 | 62 |
    63 |
    64 |
    65 |
    66 |
    67 | {% endblock %} 68 | 69 | {% block script %} 70 | 94 | {% endblock %} 95 | -------------------------------------------------------------------------------- /syzoj/templates/error_info.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 | 9 |
    10 |

    {{ info }}

    11 |
    12 | {% endblock %} 13 | 14 | {% block script %} 15 | 21 | {% endblock %} -------------------------------------------------------------------------------- /syzoj/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
    4 |
    5 |
    6 |
    7 |

    公告板

    8 |
    9 |
    10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
    标题时间
    SYZOJ使用指南2015-8-10
    题目分类列表2015-09-04
    如何添加题目2015-09-04
    mask、include、wuguangzhao等同学注意注意2015-09-19
    36 |
    37 |
    38 |
    39 |
    40 |

    排名

    41 |
    42 |
    43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | {% set rank = 1 %} 53 | {% set users = ranker.get() %} 54 | {% for user in users%} 55 | 56 | {%set rank=rank+1%} 57 | 58 | 59 | 60 | {% endfor %} 61 | 62 |
    #昵称个性签名
    {{rank}}{{user.nickname}}{% if user.nameplate %}{{user.nameplate|safe}}{% endif %}{% if user.information%}{{user.information}}{%endif%}
    63 |
    64 |
    65 |
    66 |
    67 |
    68 |
    69 |

    信息栏

    70 |
    71 |
    72 |

    请大家不要肆意复制别人代码提交!!!

    73 |
    74 |
    75 |
    76 |
    77 |

    近期比赛

    78 |
    79 |
    80 |

    还没有举行过任何比赛

    81 |
    82 |
    83 |
    84 |
    85 | {% endblock %} 86 | -------------------------------------------------------------------------------- /syzoj/templates/judge_detail.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
    4 |
    5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {% set see_result=judge.is_allowed_see_result(user) %} 19 | {% set result=judge.get_result()%} 20 | 21 | 22 | 23 | {% if see_result %} 24 | 25 | 26 | 27 | {% else %} 28 | 29 | 30 | 31 | {% endif %} 32 | 33 | 34 | 35 | 36 |
    编号题目名称状态分数总时间提交者提交时间
    {{judge.id}}{{judge.problem.title}}{{result["status"]}}{{result["score"]}}{{result["total_time"]}}隐藏隐藏隐藏{{judge.user.nickname}}{{tool.pretty_time(judge.submit_time)}}
    37 |
    38 |
    39 | {% set see_code = judge.is_allowed_see_code(user) %} 40 | {% if see_code%} 41 |
    {{judge.code}}
    42 | {% else %} 43 |
    =。=现在不可以看代码!
    44 | {% endif %} 45 |
    46 | {% if see_code and see_result%} 47 | {% if result["status"] == "Compile Error" and result["compiler_output"] %} 48 |
    49 |
    {{result["compiler_output"]}}
    50 |
    51 | {% else %} 52 |
    53 |
    54 | {% for i in range(result["case_num"]) %} 55 |
    56 | {% set case = result[tool.to_str(i)]%} 57 |
    测试点:{{i + 1}} 状态:{{case["status"]}} 58 | 运行时间:{{case["time_used"]}}ms 使用内存:{{case["memory_used"]}}kb 59 |
    60 |
    61 |
    62 | 输入文件 63 |
    {{case["input"]}}
    64 | 期望输出 65 |
    {{case["answer"]}}
    66 | 你的输出 67 |
    {{case["user_out"]}}
    68 |
    69 |
    70 |
    71 | {% endfor %} 72 |
    73 |
    74 | {% endif %} 75 | {% endif %} 76 |
    77 | {% endblock %} 78 | 79 | {% block script %} 80 | 88 | {% endblock %} 89 | -------------------------------------------------------------------------------- /syzoj/templates/judge_state.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
    4 |

    评测记录

    5 |
    6 |
    7 | 8 |
    9 |
    10 | 11 |
    12 | 13 |
    14 |
    15 | 我的提交 16 |
    17 |
    18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | {% for judge in judges %} 32 | {% set see_result=judge.is_allowed_see_result(user) %} 33 | {% set result=judge.get_result()%} 34 | 35 | 36 | 37 | {% if see_result %} 38 | 39 | 40 | 41 | {% if judge.is_allowed_see_code(user) %} 42 | 43 | {% else %} 44 | 45 | {% endif %} 46 | 47 | 48 | {% else %} 49 | 50 | 51 | 52 | {% endif %} 53 | 54 | 55 | 56 | {% endfor %} 57 | 58 |
    编号
    题目名称
    状态
    分数
    总时间
    提交者
    提交时间
    {{judge.id}}
    {{judge.problem.title}}
    {{judge.status}}
    {{result["score"]}}
    {{result["score"]}}
    {{result["total_time"]}}
    隐藏
    隐藏
    隐藏
    {{judge.user.nickname}}
    {{tool.pretty_time(judge.submit_time)}}
    59 |
    60 |
    61 | {{sorter.get_html()|safe}} 62 |
    63 | {% endblock %} 64 | -------------------------------------------------------------------------------- /syzoj/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | SYZOJ 9 | 10 | 11 | 12 | 13 | 14 | 15 | 31 | 32 | 33 | 34 |
    35 |
    36 |

    37 | SYZOJ 38 |

    39 | 40 |
    41 |
    42 | 53 |
    54 | {% set user=tool.get_cur_user() %} 55 | {% if user %} 56 |
    57 | 69 |
    70 | {% else %} 71 |
    72 | 75 | 78 |
    79 | {% endif %} 80 |
    81 |
    82 |
    83 | 84 | {% block body %}{% endblock %} 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 114 | {% block script %}{% endblock %} 115 | 116 |
    117 | 120 | 123 |
    124 | 125 | 126 | -------------------------------------------------------------------------------- /syzoj/templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
    4 |
    5 |

    登陆

    6 | 7 | 10 |
    11 |
    12 | 13 | 14 |
    15 | 16 |
    17 |
    18 |
    19 | 20 | 21 |
    22 | 23 |
    24 |
    25 | 26 |
    27 |
    28 |

    登陆

    29 |
    30 |
    31 |
    32 | 33 |
    34 |
    35 | {% endblock %} 36 | {% block script %} 37 | 95 | {% endblock %} 96 | -------------------------------------------------------------------------------- /syzoj/templates/problem.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 | 11 |
    12 |
    13 |

    {{problem.title}}{% if not problem.is_public %}--[未审核]{% endif %}

    14 | 15 |

    16 | 内存限制: {{problem.memory_limit}} MB 17 | 时间限制: {{problem.time_limit}} ms 18 |

    19 |
    20 |
    21 | 提交此题 22 | 此题提交情况 23 | {% if problem.is_allowed_edit(user) %} 24 | 编辑题面 25 | 上传测试数据 26 | {% endif %} 27 | 28 | {% if user and user.have_privilege(2) %} 29 | {% if problem.is_public %} 30 | 31 | {%else%} 32 | 33 | {%endif %} 34 | {% endif %} 35 |
    36 |
    37 |
    38 | 39 |

    题目描述

    40 |
    {{problem.description}}
    41 | 42 |

    输入格式

    43 |
    {{problem.input_format}}
    44 | 45 |

    输出格式

    46 |
    {{problem.output_format}}
    47 | 48 |

    测试样例

    49 |
    {{problem.example}}
    50 | 51 |

    数据范围与提示

    52 |
    {{problem.limit_and_hint}}
    53 |
    54 |
    55 |
    56 | {% endblock %} 57 | {% block script %} 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 115 | {% endblock %} 116 | -------------------------------------------------------------------------------- /syzoj/templates/problem_set.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
    4 |

    题库

    5 |
    6 |
    7 | 8 |
    9 | 10 |
    11 |
    12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | {% if user %} 24 | {% set submitted_problem = user.get_submitted_problems() %} 25 | {% endif %} 26 | {% for problem in problems %} 27 | {% if problem.is_allowed_use(user) %} 28 | 29 | {% if user and submitted_problem.has_key(problem.id) %} 30 | {% if submitted_problem[problem.id][0] == True %} 31 | 32 | {% else %} 33 | 34 | {% endif %} 35 | {% else %} 36 | 37 | {% endif %} 38 | 39 | 40 | 41 | 42 | 43 | {% endif %} 44 | {% endfor %} 45 | 46 |
    编号
    题目名称
    通过
    提交
    {{problem.id}}
    {{problem.title}}{% if not problem.is_public %}--[未审核]{% endif %}
    {{problem.ac_num}}
    {{problem.submit_num}}
    47 |
    48 | 49 | {{sorter.get_html()|safe}} 50 |
    51 | {% endblock %} 52 | -------------------------------------------------------------------------------- /syzoj/templates/ranklist.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
    4 |

    排名

    5 |
    6 |
    7 | 8 |
    9 | 10 |
    11 |
    12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% set rank = sorter.per_page*(sorter.cur_page-1)+1%} 23 | {% set users = sorter.get() %} 24 | {% for user in users%} 25 | 26 | {%set rank=rank+1%} 27 | 28 | 29 | 30 | 31 | {% endfor %} 32 | 33 |
    排名
    用户昵称
    个性签名
    通过数量
    {{rank}}{{user.nickname}}{% if user.nameplate %}{{user.nameplate|safe}}{% endif %}{% if user.information%}{{user.information}}{%endif%}{{user.ac_num}}
    34 |
    35 | 36 | {{sorter.get_html()|safe}} 37 |
    38 | {%endblock%} 39 | -------------------------------------------------------------------------------- /syzoj/templates/sign_up.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
    4 |
    5 |

    注册

    6 | 7 | 10 |
    11 |
    12 |
    13 | 14 | 15 |
    16 | 17 |
    18 |
    19 |
    20 | 21 | 22 |
    23 | 24 |
    25 |
    26 |
    27 | 28 | 29 |
    30 |
    31 | 32 | 33 |
    34 |
    35 |
    36 | 37 |
    38 |
    39 |

    注册

    40 |
    41 |
    42 |
    43 |
    44 |
    45 |
    46 | {% endblock %} 47 | 48 | {% block script %} 49 | 124 | {% endblock %} 125 | -------------------------------------------------------------------------------- /syzoj/templates/submit.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
    4 |
    5 |

    提交{{problem.title}}的代码

    6 |
    7 |
    8 | 9 | 12 | 13 |
    14 |
    15 | 16 | 17 |
    18 | 19 |
    20 |
    21 |
    22 | {% endblock %} -------------------------------------------------------------------------------- /syzoj/templates/upload_testdata.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
    4 |
    5 | {% if problem.testdata %} 6 |

    数据包:{{problem.testdata.filename}}

    7 | {% set ok,list=parse(problem.testdata) %} 8 | {% if ok %} 9 |

    你已经上传了测试数据,并且已经解析出以下数据点

    10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {% for case in list %} 19 | 20 | 21 | 22 | 23 | {% endfor %} 24 | 25 |
    输入文件输出文件
    {{case[0]}}{{case[1]}}
    26 | {% else %} 27 |

    你已经上传了测试数据,但是数据包出现错误{{list}}

    28 | {% endif %} 29 | {% else %} 30 |

    你还没有上传数据

    31 | {% endif %} 32 |
    33 |
    34 |
    35 |
    36 | 37 | 38 |
    39 |
    40 | 41 | 42 |
    43 |
    44 | 45 | 46 |

    数据格式请看...

    47 |
    48 | 49 |
    50 |
    51 |
    52 | {% endblock %} -------------------------------------------------------------------------------- /syzoj/templates/user.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
    4 |

    用户信息

    5 |
    6 |
    7 |
    8 |
    9 |

    头像

    10 |
    11 |
    12 | 13 |
    14 |
    15 |
    16 |
    17 |
    18 |
    19 |

    用户昵称

    20 |
    21 |
    22 |

    {{shown_user.nickname}}{%if shown_user.nameplate %}{{shown_user.nameplate|safe}}{%endif%}

    23 |
    24 | 25 |
    26 |

    用户邮箱

    27 |
    28 |
    29 |

    {{shown_user.email}}

    30 |
    31 |
    32 |
    33 | 34 |
    35 |
    36 |
    37 |

    共发表了{{ articles_num }}篇文章

    38 |
    39 |
    40 | 41 | 42 | {% for article in articles %} 43 | 44 | 45 | 46 | 47 | {% endfor %} 48 | 49 |
    {{article.title}}{{tool.pretty_time(article.public_time)}}
    50 |
    51 |
    52 |
    53 |
    54 |
    55 |
    56 |
    57 |

    个性签名

    58 |
    59 |
    60 |

    {%if shown_user.information%}{{shown_user.information}}{%else%}泥萌看什么看,{{shown_user.nickname}}什么都没有说{%endif%}

    61 |
    62 |
    63 |
    64 |
    一共通过了{{shown_user.ac_num}}道题
    65 | {% set submitted_problems = shown_user.get_submitted_problems() %} 66 |
    67 | {% for key in submitted_problems.keys() %} 68 | {% if submitted_problems[key][0] == True %} 69 | {{key}} 70 | {% endif %} 71 | {% endfor %} 72 |
    73 |
    74 |
    75 |
    76 | {% endblock %} 77 | -------------------------------------------------------------------------------- /syzoj/templates/virtual_contest.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block body %} 3 |
    4 |

    {{ contest.title }}

    5 |
    6 |
    7 |
    8 | {{ contest.information }} 9 |
    10 |
    11 |
    12 |
    13 | 14 | 15 |
    16 |
    17 |
    18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /syzoj/update_assistant/misc.py: -------------------------------------------------------------------------------- 1 | from syzoj.models import JudgeState 2 | from syzoj import db 3 | 4 | db.create_all() 5 | 6 | all_judge = JudgeState.query.all() 7 | for item in all_judge: 8 | item.update_userac_info() 9 | -------------------------------------------------------------------------------- /syzoj/views/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import request, render_template 2 | 3 | from syzoj import oj,db 4 | from syzoj.models import User 5 | from syzoj.controller import Tools, Paginate 6 | from .session import sign_up, login 7 | from .problem import problem, problem_set 8 | from .judge import submit_code, judge_state 9 | from .user import user, edit_user 10 | from .discussion import edit_article, article, discussion 11 | from .contest import contest_list 12 | 13 | 14 | @oj.route("/") 15 | def index(): 16 | query = User.query.order_by(db.desc(User.ac_num)) 17 | ranker = Paginate(query, cur_page=1, per_page=10) 18 | return render_template("index.html", tool=Tools, tab="index", ranker=ranker) 19 | 20 | 21 | @oj.route("/error") 22 | def error(): 23 | info = request.args.get("info") 24 | next = request.args.get("next") 25 | #TODO:rewrite error page for beautiful 26 | return render_template("error_info.html", tool=Tools, info=info, next=next) -------------------------------------------------------------------------------- /syzoj/views/common.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from flask import redirect, url_for 4 | 5 | 6 | def show_error(error, next): 7 | return redirect(url_for("error", info=error, next=next)) 8 | 9 | 10 | def need_login(): 11 | return show_error("Please login first.", url_for("login")) 12 | 13 | 14 | def not_have_permission(): 15 | return show_error("You don't have permission", url_for("index")) -------------------------------------------------------------------------------- /syzoj/views/contest.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from urllib import urlencode 4 | import time 5 | from flask import render_template, url_for, request, abort, redirect 6 | from syzoj import oj, db 7 | from syzoj.models import Contest, User, JudgeState 8 | from syzoj.controller import Tools, Paginate 9 | from .common import need_login, not_have_permission 10 | 11 | 12 | @oj.route("/contest") 13 | def contest_list(): 14 | query = Contest.query.order_by(db.desc(Contest.start_time)) 15 | 16 | def make_url(page, other): 17 | return url_for("contest_list") + "?" + urlencode({"page": page}) 18 | 19 | sorter = Paginate(query, make_url=make_url, cur_page=request.args.get("page"), edge_display_num=3, per_page=10) 20 | return render_template("contest_list.html", tool=Tools, sorter=sorter, now=time.time()) 21 | 22 | 23 | @oj.route("/contest/") 24 | def contest(contest_id): 25 | contest = Contest.query.filter_by(id=contest_id).first() 26 | user = User.get_cur_user() 27 | 28 | now = time.time() 29 | if now < contest.start_time and not contest.is_allowed_edit(user): 30 | return not_have_permission() 31 | 32 | player = None 33 | info = {} 34 | if user: player = contest.players.filter_by(user_id = user.id).first() 35 | if player: 36 | details = player.get_score_details() 37 | for key, val in details.iteritems(): 38 | if isinstance(val, dict): 39 | pid = int(key) 40 | jid = int(val["judge_id"]) 41 | status = JudgeState.query.filter_by(id = jid).first().status 42 | url = url_for("judge_detail", judge_id = jid) 43 | if contest.is_running(): 44 | info[pid] = u"已提交" % (url) 45 | else: 46 | info[pid] = "%s" % (url, status) 47 | 48 | return render_template("contest.html", tool=Tools, contest=contest, info = info) 49 | 50 | 51 | @oj.route("/contest//") 52 | def contest_problem(contest_id, kth_problem): 53 | contest = Contest.query.filter_by(id=contest_id).first() 54 | user = User.get_cur_user() 55 | if not contest: 56 | abort(404) 57 | 58 | now = time.time() 59 | if now < contest.start_time and not contest.is_allowed_edit(user): 60 | return not_have_permission() 61 | 62 | problem = contest.get_problems()[kth_problem] 63 | if now > contest.end_time: 64 | return redirect(url_for("problem", problem_id=problem.id)) 65 | 66 | return render_template("contest_problem.html", tool=Tools, problem=problem, contest=contest) 67 | 68 | 69 | @oj.route("/contest//ranklist") 70 | def contest_ranklist(contest_id): 71 | user = User.get_cur_user() 72 | contest = Contest.query.filter_by(id=contest_id).first() 73 | if not contest: 74 | abort(404) 75 | now = time.time() 76 | if contest.is_allowed_edit(user) or now > contest.end_time: 77 | return render_template("contest_ranklist.html", tool=Tools, contest=contest) 78 | else: 79 | return not_have_permission() 80 | 81 | 82 | @oj.route("/contest//edit", methods=["GET", "POST"]) 83 | def edit_contest(contest_id): 84 | user = User.get_cur_user() 85 | if not user: 86 | return need_login() 87 | 88 | contest = Contest.query.filter_by(id=contest_id).first() 89 | if contest and not contest.is_allowed_edit(user): 90 | return not_have_permission() 91 | elif not (user.have_privilege(4) or user.have_privilege(5)): 92 | return not_have_permission() 93 | 94 | if request.method == "POST": 95 | if not contest: 96 | contest = Contest(title=request.form.get("title"), 97 | start_time=request.form.get("start_time"), 98 | end_time=request.form.get("end_time"), 99 | holder=user) 100 | 101 | contest.title = request.form.get("title") 102 | contest.start_time = request.form.get("start_time") 103 | contest.end_time = request.form.get("end_time") 104 | contest.information = request.form.get("information") 105 | 106 | try: 107 | problems_list = [int(pid) for pid in request.form.get("problems").split(",")] 108 | except: 109 | problems_list = [] 110 | contest.set_problems(problems_list) 111 | 112 | contest.save() 113 | 114 | return redirect(url_for("contest", contest_id=contest.id)) 115 | else: 116 | return render_template("edit_contest.html", tool=Tools, contest=contest) 117 | -------------------------------------------------------------------------------- /syzoj/views/discussion.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import time 3 | from urllib import urlencode 4 | 5 | from flask import redirect, url_for, request, render_template, abort 6 | 7 | from syzoj import oj 8 | from syzoj.models import User, Article, Comment 9 | from syzoj.controller import Paginate, Tools 10 | from .common import need_login, not_have_permission, show_error 11 | 12 | 13 | @oj.route("/discussion") 14 | def discussion(): 15 | query = Article.query.order_by(Article.sort_time.desc()) 16 | 17 | def make_url(page, other): 18 | return url_for("discussion") + "?" + urlencode({"page": page}) 19 | 20 | sorter = Paginate(query, make_url=make_url, cur_page=request.args.get("page"), edge_display_num=3, per_page=10) 21 | return render_template("discussion.html", tool=Tools, tab="discussion", sorter=sorter) 22 | 23 | 24 | @oj.route("/article/") 25 | def article(article_id): 26 | article = Article.query.filter_by(id=article_id).first() 27 | if not article: 28 | return show_error("找不到文章", url_for('index')) 29 | 30 | comments = Comment.query.filter_by(article_id=article_id) 31 | comments_num = comments.count() 32 | 33 | def make_url(page, other): 34 | return url_for("article", article_id=article_id) + "?" + urlencode({"page": page}) 35 | sorter = Paginate(comments, make_url=make_url, cur_page=request.args.get("page"), edge_display_num=3, per_page=10) 36 | 37 | return render_template("article.html", tool=Tools, article=article, 38 | comment_num=comments_num, sorter=sorter, tab="discussion") 39 | 40 | 41 | @oj.route("/article//edit", methods=["GET", "POST"]) 42 | def edit_article(article_id): 43 | user = User.get_cur_user() 44 | if not user: 45 | return need_login() 46 | 47 | article = Article.query.filter_by(id=article_id).first() 48 | if article and article.is_allowed_edit(user) == False: 49 | return not_have_permission() 50 | 51 | if request.method == "POST": 52 | if request.form.get("title") == "" or request.form.get("content") == "": 53 | return show_error("Please input title and content", 54 | url_for("edit_article", article_id=article_id)) 55 | if not article: 56 | article = Article(title=request.form.get("title"), content=request.form.get("content"), user=user) 57 | 58 | article.title = request.form.get("title") 59 | article.content = request.form.get("content") 60 | article.update_time = time.time() 61 | article.sort_time = time.time() 62 | article.save() 63 | return redirect(url_for("article", article_id=article.id)) 64 | else: 65 | return render_template("edit_article.html", tool=Tools, article=article, tab="discussion") 66 | 67 | 68 | @oj.route("/article//delete") 69 | def delete_article(article_id): 70 | user = User.get_cur_user() 71 | article = Article.query.filter_by(id=article_id).first() 72 | 73 | if not user: 74 | return need_login() 75 | 76 | if not article: 77 | return show_error("Can't find article", url_for('index')) 78 | 79 | if article and article.is_allowed_edit(user) == False: 80 | return not_have_permission() 81 | 82 | if request.args.get("confirm") == "true": 83 | article = Article.query.filter_by(id=article_id).first() 84 | if article and article.is_allowed_edit(user) == False: 85 | return not_have_permission() 86 | 87 | if article: 88 | article.delete() 89 | return redirect(url_for("discussion")) 90 | else: 91 | return render_template("delete_article.html", tool = Tools, user=user, article=article) 92 | 93 | 94 | @oj.route("/article//comment", methods=["POST"]) 95 | def comment_article(article_id): 96 | user = User.get_cur_user() 97 | article = Article.query.filter_by(id=article_id).first() 98 | if not article: 99 | abort(404) 100 | if not user: 101 | return need_login() 102 | 103 | comment_str = request.form.get("comment") 104 | if not comment_str.replace(" ", ""): 105 | return show_error("请输入评论", 106 | next=url_for("article", article_id=article_id)) 107 | 108 | comment = Comment(comment_str, article, user) 109 | comment.save() 110 | 111 | return redirect(url_for("article", article_id=article.id)) 112 | -------------------------------------------------------------------------------- /syzoj/views/judge.py: -------------------------------------------------------------------------------- 1 | from urllib import urlencode 2 | import json 3 | 4 | from flask import jsonify, redirect, url_for, abort, request, render_template 5 | 6 | from syzoj import oj, db 7 | from syzoj.controller import Tools 8 | from syzoj.models import JudgeState, WaitingJudge, Problem, User, Contest 9 | from syzoj.controller import Paginate 10 | from .common import need_login, not_have_permission, show_error 11 | 12 | 13 | @oj.route("/submit/", methods=["GET", "POST"]) 14 | def submit_code(problem_id): 15 | user = User.get_cur_user() 16 | if not user: 17 | return need_login() 18 | 19 | problem = Problem.query.filter_by(id=problem_id).first() 20 | if not problem: 21 | abort(404) 22 | 23 | if request.method == "POST": 24 | code = request.form.get("code") 25 | language = "C++" 26 | if not code or len(code) <= 0 or len(code) >= 1024 * 100: 27 | return show_error("Please check out your code length.The code should less than 100kb.", 28 | url_for("submit_code", problem_id=problem.id)) 29 | 30 | judge = JudgeState(code=code, user=user, language=language, problem=problem) 31 | 32 | contest_id = request.args.get("contest_id") 33 | if contest_id: 34 | contest = Contest.query.filter_by(id=contest_id).first() 35 | if contest and contest.is_running(): 36 | judge.type = 1 37 | judge.type_info = contest_id 38 | else: 39 | return show_error("Sorry.The contest has been ended.", next=url_for("contest", contest_id=contest.id)) 40 | else: 41 | if not problem.is_allowed_use(user): 42 | return show_error("Sorry.You don't have permission.", next=url_for("index")) 43 | if not problem.is_public: 44 | judge.type = 2 45 | 46 | judge.save() 47 | waiting = WaitingJudge(judge) 48 | waiting.save() 49 | return redirect(url_for("judge_detail", judge_id=judge.id)) 50 | else: 51 | return render_template("submit.html", tool=Tools, problem=problem, tab="judge") 52 | 53 | 54 | @oj.route("/judge_state") 55 | def judge_state(): 56 | query = JudgeState.query.order_by(db.desc(JudgeState.id)) 57 | nickname = request.args.get("submitter") 58 | problem_id = request.args.get("problem_id") 59 | if request.args.get("submitter"): 60 | submitter = User.query.filter_by(nickname=nickname).first() 61 | if submitter: 62 | submitter_id = submitter.id 63 | else: 64 | submitter_id = 0 65 | query = query.filter_by(user_id=submitter_id) 66 | if request.args.get("problem_id"): 67 | query = query.filter_by(problem_id=int(problem_id)) 68 | 69 | def make_url(page, other): 70 | other["page"] = page 71 | return url_for("judge_state") + "?" + urlencode(other) 72 | 73 | if not nickname: 74 | nickname = "" 75 | if not problem_id: 76 | problem_id = "" 77 | sorter = Paginate(query, make_url=make_url, other={"submitter": nickname, "problem_id": problem_id}, 78 | cur_page=request.args.get("page"), edge_display_num=3, per_page=10) 79 | 80 | return render_template("judge_state.html", user=User.get_cur_user(), judges=sorter.get(), tab="judge", 81 | submitter=nickname, problem_id=problem_id, sorter=sorter, encode=urlencode, tool=Tools) 82 | 83 | 84 | @oj.route("/api/waiting_judge", methods=["GET"]) 85 | def get_judge_info(): 86 | session_id = request.args.get('session_id') 87 | if oj.config["JUDGE_TOKEN"] != session_id: 88 | abort(404) 89 | 90 | waiting_judge = WaitingJudge.query.first() 91 | if not waiting_judge: 92 | return jsonify({"have_task": 0}) 93 | judge = waiting_judge.judge 94 | waiting_judge.delete() 95 | 96 | return jsonify({"have_task": 1, 97 | "judge_id": judge.id, 98 | "code": judge.code, 99 | "language": judge.language, 100 | "testdata": judge.problem.testdata.md5, 101 | "time_limit": judge.problem.time_limit, 102 | "memory_limit": judge.problem.memory_limit}) 103 | 104 | 105 | @oj.route("/api/update_judge/", methods=["POST"]) 106 | def update_judge_info(judge_id): 107 | token = request.args.get('session_id') 108 | if oj.config["JUDGE_TOKEN"] != token: 109 | abort(404) 110 | 111 | judge = JudgeState.query.filter_by(id=judge_id).first() 112 | if not judge: 113 | abort(404) 114 | 115 | judge.update_result(json.loads(request.form["result"])) 116 | judge.update_userac_info() 117 | judge.update_related_info() 118 | judge.save() 119 | 120 | return jsonify({"return": 0}) 121 | 122 | 123 | @oj.route("/judge_detail/") 124 | def judge_detail(judge_id): 125 | judge = JudgeState.query.filter_by(id=judge_id).first() 126 | if not judge: 127 | abort(404) 128 | 129 | return render_template("judge_detail.html", judge=judge, user=User.get_cur_user(), tab="judge", tool=Tools) 130 | -------------------------------------------------------------------------------- /syzoj/views/problem.py: -------------------------------------------------------------------------------- 1 | import sys 2 | reload(sys) 3 | sys.setdefaultencoding("utf8") 4 | 5 | from urllib import urlencode 6 | 7 | from flask import jsonify, redirect, url_for, abort, request, render_template 8 | 9 | from syzoj import oj, controller 10 | from syzoj.models import User, Problem, File, FileParser 11 | from syzoj.controller import Paginate, Tools 12 | from .common import need_login, not_have_permission, show_error 13 | 14 | 15 | @oj.route("/problem") 16 | def problem_set(): 17 | query = Problem.query 18 | problem_title = request.args.get("problem_title") 19 | 20 | if request.args.get("problem_title"): 21 | query = query.filter(Problem.title.like((u"%" + problem_title + u"%"))) 22 | else: 23 | problem_title = '' 24 | 25 | def make_url(page, other): 26 | other["page"] = page 27 | return url_for("problem_set") + "?" + urlencode(other) 28 | 29 | sorter = Paginate(query, make_url=make_url, other={"problem_title": problem_title}, 30 | cur_page=request.args.get("page"), edge_display_num=50, per_page=50) 31 | 32 | return render_template("problem_set.html", tool=Tools, tab="problem_set", sorter=sorter, problems=sorter.get()) 33 | 34 | 35 | @oj.route("/problem/") 36 | def problem(problem_id): 37 | user = User.get_cur_user() 38 | 39 | problem = Problem.query.filter_by(id=problem_id).first() 40 | if not problem: 41 | abort(404) 42 | 43 | if problem.is_allowed_use(user) == False: 44 | return not_have_permission() 45 | 46 | return render_template("problem.html", tool=Tools, tab="problem_set", problem=problem) 47 | 48 | 49 | @oj.route("/problem//edit", methods=["GET", "POST"]) 50 | def edit_problem(problem_id): 51 | user = User.get_cur_user() 52 | if not user: 53 | return need_login() 54 | 55 | problem = Problem.query.filter_by(id=problem_id).first() 56 | if problem and problem.is_allowed_edit(user) == False: 57 | return not_have_permission() 58 | 59 | if request.method == "POST": 60 | if not problem: 61 | problem_id = controller.create_problem(user=user, title=request.form.get("title")) 62 | problem = Problem.query.filter_by(id=problem_id).first() 63 | problem.update(title=request.form.get("title"), 64 | description=request.form.get("description"), 65 | input_format=request.form.get("input_format"), 66 | output_format=request.form.get("output_format"), 67 | example=request.form.get("example"), 68 | limit_and_hint=request.form.get("limit_and_hint")) 69 | 70 | problem.save() 71 | 72 | return redirect(url_for("problem", problem_id=problem.id)) 73 | else: 74 | return render_template("edit_problem.html", tool=Tools, problem=problem) 75 | 76 | 77 | @oj.route("/problem//upload", methods=["GET", "POST"]) 78 | def upload_testdata(problem_id): 79 | user = User.get_cur_user() 80 | if not user: 81 | return need_login() 82 | 83 | problem = Problem.query.filter_by(id=problem_id).first() 84 | if not problem: 85 | abort(404) 86 | if problem.is_allowed_edit(user) == False: 87 | return not_have_permission() 88 | if request.method == "POST": 89 | file = request.files.get("testdata") 90 | if file: 91 | problem.update_testdata(file) 92 | if request.form.get("time_limit"): 93 | problem.time_limit = int(request.form.get("time_limit")) 94 | if request.form.get("memory_limit"): 95 | problem.memory_limit = int(request.form.get("memory_limit")) 96 | problem.save() 97 | return redirect(url_for("upload_testdata", problem_id=problem_id)) 98 | else: 99 | return render_template("upload_testdata.html", tool=Tools, problem=problem, parse=FileParser.parse_as_testdata) 100 | 101 | 102 | # TODO:Maybe need add the metho of toggle is_public attr to Problem 103 | @oj.route("/api/problem//public", methods=["POST", "DELETE"]) 104 | def change_public_attr(problem_id): 105 | session_id = request.args.get('session_id') 106 | user = User.get_cur_user(session_id=session_id) 107 | problem = Problem.query.filter_by(id=problem_id).first() 108 | if problem and user and user.have_privilege(2): 109 | if request.method == "POST": 110 | problem.is_public = True 111 | elif request.method == "DELETE": 112 | problem.is_public = False 113 | problem.save() 114 | else: 115 | abort(404) 116 | return jsonify({"status": 0}) 117 | -------------------------------------------------------------------------------- /syzoj/views/session.py: -------------------------------------------------------------------------------- 1 | from flask import jsonify, request, render_template 2 | 3 | from syzoj import oj 4 | from syzoj.models import User, Session 5 | from syzoj.controller import Tools 6 | from syzoj import controller 7 | 8 | @oj.route("/login") 9 | def login(): 10 | return render_template("login.html", tool=Tools) 11 | 12 | 13 | @oj.route("/sign_up") 14 | def sign_up(): 15 | return render_template("sign_up.html", tool=Tools) 16 | 17 | 18 | @oj.route("/api/sign_up", methods=["POST"]) 19 | def api_sign_up(): 20 | username = request.args.get('username') 21 | password = request.args.get('password') 22 | email = request.args.get('email') 23 | error_code = controller.register(username, password, email) 24 | return jsonify({"error_code": error_code}) 25 | 26 | 27 | @oj.route("/api/login", methods=["POST"]) 28 | def api_login(): 29 | error_code = 1 30 | session_id = "???" 31 | username = request.form.get('username') 32 | password = request.form.get('password') 33 | user = User.query.filter_by(username=username).first() 34 | if not user: 35 | error_code = 1001 36 | elif user.password != password: 37 | error_code = 1002 38 | else: 39 | session = Session(user) 40 | session.save() 41 | session_id = session.id 42 | return jsonify({"error_code": error_code, "session_id": session_id}) 43 | 44 | 45 | @oj.route("/api/logout", methods=["POST"]) 46 | def api_logout(): 47 | session_id = request.args.get('session_id') 48 | user = User.get_cur_user(session_id=session_id) 49 | sessions = user.sessions.all() 50 | for s in sessions: 51 | s.delete() 52 | return jsonify({"status": "1"}) -------------------------------------------------------------------------------- /syzoj/views/user.py: -------------------------------------------------------------------------------- 1 | from flask import redirect, url_for, request, render_template 2 | 3 | from syzoj import oj, db 4 | from syzoj.models import User, Article 5 | from syzoj.controller import Paginate, Tools, Checker 6 | from .common import not_have_permission, show_error 7 | 8 | @oj.route("/user/") 9 | def user(user_id): 10 | user = User.find_user(id=user_id) 11 | if not user: 12 | return show_error("Can't find user", next=url_for("index")) 13 | 14 | user.refresh_submit_info() 15 | user.save() 16 | 17 | articles = Article.query.filter_by(user_id = user.id).order_by(Article.public_time.desc()).all() 18 | articles_num = len(articles) 19 | 20 | return render_template("user.html", tool=Tools, shown_user=user, 21 | articles_num = articles_num, articles = articles) 22 | 23 | @oj.route("/user//edit", methods=["GET", "POST"]) 24 | def edit_user(user_id): 25 | edited_user = User.find_user(id=user_id) 26 | if not edited_user: 27 | return show_error("Can't find user", next=url_for("index")) 28 | 29 | user = User.get_cur_user() 30 | if not edited_user.is_allowed_edit(user): 31 | return not_have_permission() 32 | 33 | if request.method == "POST": 34 | email = request.form.get("email") 35 | information = request.form.get("information") 36 | old_password = request.form.get("old_password") 37 | new_password = request.form.get("new_password") 38 | if user.have_privilege(1): 39 | if request.form.get("prb_mng"): 40 | edited_user.give_privilege(2) 41 | else: 42 | edited_user.del_privilege(2) 43 | if request.form.get("vwa_prb"): 44 | edited_user.give_privilege(3) 45 | else: 46 | edited_user.del_privilege(3) 47 | if request.form.get("cts_mng"): 48 | edited_user.give_privilege(4) 49 | else: 50 | edited_user.del_privilege(4) 51 | if request.form.get("cts_bld"): 52 | edited_user.give_privilege(5) 53 | else: 54 | edited_user.del_privilege(5) 55 | if request.form.get("atc_mng"): 56 | edited_user.give_privilege(6) 57 | else: 58 | edited_user.del_privilege(6) 59 | if request.form.get("usr_mng"): 60 | edited_user.give_privilege(7) 61 | else: 62 | edited_user.del_privilege(7) 63 | if request.form.get("dat_dld"): 64 | edited_user.give_privilege(8) 65 | else: 66 | edited_user.del_privilege(8) 67 | 68 | status = 1 69 | if not Checker.is_valid_email(email): 70 | status = 3001 71 | 72 | if information == "": 73 | information = None 74 | 75 | if old_password: 76 | if edited_user.password != old_password: 77 | status = 3002 78 | else: 79 | if Checker.is_valid_password(new_password): 80 | edited_user.password = new_password 81 | else: 82 | status = 3003 83 | 84 | if status == 1: 85 | edited_user.email = email 86 | edited_user.information = information 87 | edited_user.save() 88 | 89 | return render_template("edit_user.html", tool=Tools, edited_user=edited_user, status=status) 90 | else: 91 | return render_template("edit_user.html", tool=Tools, edited_user=edited_user) 92 | 93 | 94 | @oj.route("/ranklist") 95 | def ranklist(): 96 | query = User.query.order_by(db.desc(User.ac_num)) 97 | 98 | def make_url(page, other): 99 | return url_for("ranklist") + "?" + Tools.url_encode({"page": page}) 100 | 101 | sorter = Paginate(query, make_url=make_url, cur_page=request.args.get("page"), edge_display_num=3, per_page=50) 102 | 103 | return render_template("ranklist.html", tool=Tools, sorter=sorter, tab="ranklist") 104 | 105 | 106 | @oj.route("/find_user") 107 | def find_user(): 108 | nickname = request.args.get("nickname") 109 | user = User.find_user(nickname=nickname) 110 | if not user: 111 | return show_error("Can't find " + nickname, url_for("ranklist")) 112 | 113 | return redirect(url_for("user", user_id=user.id)) 114 | -------------------------------------------------------------------------------- /test/test_contest.py: -------------------------------------------------------------------------------- 1 | import syzoj 2 | from syzoj.models.contest import * 3 | from syzoj.models.user import * 4 | import unittest 5 | import time 6 | 7 | 8 | class TestContest(unittest.TestCase): 9 | def setUp(self): 10 | self.holder = User.query.filter_by(username="abc").first() 11 | self.start_time = time.time() 12 | self.contest = Contest("test_con", self.start_time + 2, self.start_time + 5, self.holder) 13 | 14 | def test_set_problems(self): 15 | prob_list = [1, 2, 3] 16 | self.contest.set_problems(prob_list) 17 | self.contest.save() 18 | 19 | probs = self.contest.get_problems() 20 | print probs 21 | self.assertTrue(probs) 22 | 23 | def test_is_running(self): 24 | before = False 25 | running = False 26 | after = False 27 | while True: 28 | ir = self.contest.is_running() 29 | if not before: 30 | if not ir: 31 | before = True 32 | elif not running: 33 | if ir: 34 | running = True 35 | elif not after: 36 | if not ir: 37 | after = True 38 | if time.time() > self.start_time + 6: 39 | break 40 | self.assertTrue(before) 41 | self.assertTrue(running) 42 | self.assertTrue(after) 43 | -------------------------------------------------------------------------------- /test/test_controller.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import syzoj 3 | import hashlib 4 | from random import randint 5 | 6 | 7 | class TestRegister(unittest.TestCase): 8 | def md5_pass(self, password): 9 | md5 = hashlib.md5() 10 | md5.update(password) 11 | return md5.hexdigest() 12 | 13 | def test_register(self): 14 | user = "tester_%d" % randint(1, int(1e9)) 15 | pw = self.md5_pass("123_%d" % randint(1, 100)) 16 | email = "84%d@qq.com" % randint(1, 10000) 17 | print user, pw, email 18 | self.assertEqual(syzoj.controller.register(user, pw, email), 1) 19 | 20 | self.assertNotEqual(syzoj.controller.register(user, pw, email), 1) 21 | 22 | def test_multiple_register(self): 23 | rid = randint(1, 10000) 24 | for i in range(1, 2): 25 | pw = self.md5_pass("123_%d_%d" % (rid, i)) 26 | print i, pw 27 | self.assertEqual(syzoj.controller.register("hello_%d_%d" % (rid, i), pw, "%d@qq.com" % i), 1) 28 | 29 | 30 | if __name__ == "__main__": 31 | unittest.main() 32 | -------------------------------------------------------------------------------- /test/test_problem.py: -------------------------------------------------------------------------------- 1 | import syzoj 2 | from syzoj.models import Problem 3 | import unittest 4 | 5 | 6 | class TestCreateProblem(unittest.TestCase): 7 | def setUp(self): 8 | user = syzoj.models.User.query.filter_by(id=1).first() 9 | title = u"\u6D4B\u8BD5\u9898\u76EE".encode("utf-8") 10 | pid = syzoj.controller.create_problem(user, title) 11 | print pid 12 | self.problem = Problem.query.filter_by(id=pid).first() 13 | self.assertTrue(pid >= 1) 14 | 15 | def test_edit_problem(self): 16 | des = "Give you two integer A and B.Now please calculate A+B." 17 | hint = "uh...." 18 | self.problem.update(description=des) 19 | self.problem.save() 20 | self.assertEqual(self.problem.description, des) 21 | 22 | self.problem.update(limit_and_hint=hint) 23 | self.problem.save() 24 | self.assertEqual(self.problem.description, des) 25 | 26 | self.problem.is_public = True 27 | self.problem.save() 28 | --------------------------------------------------------------------------------