本文由 outloudvi 与 SchrodingerZhu 协作完成。
SchOJ 是基于 DMOJ(站点、GitHub)二次开发的在线评测(Online Judge)网站系统。
听说 DMOJ 还是在搞信息奥赛的时候。那时候 DMOJ 的官方名字还叫 Don Mills Online Judge(Don Mills 是加拿大多伦多的一个区,中文译名好像叫“唐米尔斯”)。界面不错,功能也不错,社区也有一群大佬。这次折腾 OJ ,把各种平台比较了一下,最后选择以 DMOJ 为基础进行开发。
关于其它平台
- zhblue/hustoj:老牌 OJ 平台。站点后端是 PHP 所以不考虑了。虽然过去也有写过 PHP 项目,但现在确实是对 PHP 失去兴趣了。
- QingdaoU/OnlineJudge:青岛大学的 OJ 平台。好看,确实好看,不过评测后端比较复杂,尝试加语言的时候一直没法成功,于是就略过了。(这点和 SchrodingerZhu 想加的语言本身也有关系,一会再吐槽)
- SYZOJ(Demo):功能强大,界面很棒,不过部署比较复杂...
- UOJ(Demo):配置比较复杂(有一个博客系统要做泛解析)
总而言之最后是选择了 DMOJ。DMOJ 的网站端和评测端都以 Python (2) 为主要使用语言,所以改得还是比较舒服。
做了什么事情
-
Docker 化 mainly done by outloudvi(后来发现其实已经有人做过了,我们加了一些优化,也改成了国内的镜像源,目前以
ubuntu:disco
为底包,Debian 非 sid 的话包太少了) -
前端用 Semantic UI 重制 mainly done by outloudvi。当时单推 Semantic UI,于是就做了...
-
Python 2 -> 3 mainly done by SchrodingerZhu,槽点众多。
-
加入 Scala、Elixir 语言滋瓷 (done by SchrodingerZhu)
-
加入 Unittest 评测方法 mainly done by outloudvi。目前可能只适用于 Python,而且需要对 Python 进行一点 patch,否则容易被绕过。
-
管理页面改成 JET 样式。 wpadmin 的样式实在不敢恭维。
-
在站点上加了一些 Undocumented feature,例如 OAuth 和 MathJax。虽然没有写在文档上,配置还是很方便的。
-
向上游做了一点微小的贡献
吐槽 Elixir 与 Scala
请看 DMOJ/judge!365 和 DMOJ/judge!356。
吐槽 Python 2 to 3
这点也是我们作死…把 Python 2 to 3 的更新和 Django 1.11 to 2.0 的更新同时做,然后不得不同时面对以下问题:
(以下内容来自 @SchrodingerZhu)
- Python 的 unicode、str、byte 含糊不清的暧昧关系(请善用
.encode
和.decode
) - Python 2 中有把
'zlib'
直接当作默认的encode
,decode
的解析器的用法,到Python 3
要引入codecs
或者直接采用zlib
库 ugettext_lazy
变动为了gettext_lazy
Python 2
迭代器类型next
函数变更成了魔术函数__next__
- 返回可迭代类型的迭代器应使用
iterms
而不再是iteritems
- 可重复集合不再能够直接使用
=
来重新赋值,变更为使用set()
- 部分类的
__lt__
需要重新定义 json.load
和json.loads
的区别在Python 3
要注意urllib2
要改为urllib.request
,且后者的urlopen
返回的是request
的对象,使用read()
方法才能取得返回内容- 需要二进制读写的地方注意变更
w
,r
到wb
,rb
Django
的脚手架manage.py
需要重新引入新版Django
获取模型对象名字的方法需要从__unicode__
变更为__str__
,如果迁移后某些地方出现了XXX Object (1)
而不是想要的名字,可以考虑这一点Django
的django.core.urlresolvers
变更成了django.urls
- 新版
Django
的urls
的注册namespace
的时候需要提供app_name
- 新版
Django
的Model
不再预定义Foreign Key
中的on_delete
,可以手动在模型的注册函数添加on_delete=CASCADE
Django
的query
对象原有的复制方法clone()
是静态函数,现在成为了类方法Django
的query
对象原有的rel
属性变更为remote_field
一切尽在不言中啊。(劳资的意大利炮 .gitignore
呢?!)