SchOJ 开发日志

Re:Linked

本文由 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!365DMOJ/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.loadjson.loads的区别在Python 3要注意
  • urllib2要改为urllib.request,且后者的urlopen返回的是request的对象,使用read()方法才能取得返回内容
  • 需要二进制读写的地方注意变更wrwbrb
  • Django的脚手架manage.py需要重新引入新版
  • Django获取模型对象名字的方法需要从__unicode__变更为__str__,如果迁移后某些地方出现了XXX Object (1)而不是想要的名字,可以考虑这一点
  • Djangodjango.core.urlresolvers变更成了django.urls
  • 新版Djangourls的注册namespace的时候需要提供app_name
  • 新版DjangoModel不再预定义Foreign Key中的on_delete,可以手动在模型的注册函数添加on_delete=CASCADE
  • Djangoquery对象原有的复制方法clone()是静态函数,现在成为了类方法
  • Djangoquery对象原有的rel属性变更为remote_field

一切尽在不言中啊。(劳资的意大利炮 .gitignore 呢?!)