Coder Social home page Coder Social logo

renbaoshuo / s2oj Goto Github PK

View Code? Open in Web Editor NEW
26.0 1.0 6.0 42.36 MB

Online Judge System for Shijiazhuang No.2 Middle School, based on Universal Online Judge.

Home Page: https://sjzezoj.com

License: GNU Affero General Public License v3.0

Python 0.94% PHP 50.85% Shell 0.39% Makefile 0.06% C++ 15.47% CSS 3.32% JavaScript 19.59% HTML 2.95% Dockerfile 0.13% SCSS 2.63% TypeScript 3.65%
oj online-judge oi uoj universaloj s2oj docker onlinejudge

s2oj's Introduction

Logo

S2OJ

基于 Universal Online Judge 的在线测评系统。专为 石家庄二中 设计。

特性

  • 前后端全面更新为 Bootstrap 5 + PHP 7,与 UOJ 官网的最新代码同步。
  • 使用 Docker Compose 编排服务相关容器,省心省力、方便快捷,更加灵活。
  • 各组成部分既可单点部署,也可分离部署;支持添加多个评测机。
  • 题目搜索全局放置,任意页面均可快速到达。
  • 所有题目从编译、运行到评分,都可以由出题人自定义。
  • 引入 Extra Tests 和 Hack 机制,更加严谨、更有乐趣。
  • 支持 OI/IOI/ACM 等比赛模式;比赛内设有提问区域。
  • 博客功能,不仅可撰写图文内容,也可制作幻灯片。
  • 支持赛后总结功能,从点滴反思中汲取奋进力量。
  • 更细化的权限管理。
  • 支持 Codeforces、AtCoder、UniversalOJ、LibreOJ、洛谷等平台的 Remote Judge。
  • 其他应校内训练需求而新增的功能。

文档

有关安装、管理、维护,可参阅:https://s2oj.github.io/https://universaloj.github.io/https://vfleaking.github.io/uoj/

部署

修改 docker-compose.yml 中的配置,然后执行:

docker-compose up -d

更新:

docker-compose pull
docker-compose up -d

开发

docker-compose -f docker-compose.development.yml up --build

感谢

  • vfleaking 将 UOJ 代码 开源
  • 向原项目或本项目贡献代码的人
  • 给我们启发与灵感以及提供意见和建议的人

许可

Universal Online Judge
Copyright (c) 2016-2022 vfleaking

S2OJ
Copyright (c) 2022-present Baoshuo

本项目采用 AGPL-3.0 许可协议开源,在使用本项目的源代码时请遵守许可协议。

s2oj's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

s2oj's Issues

关于新版标签系统的构想

背景

在 S2OJ 的使用过程中,题目标签一直是由题目上传者和管理员手动配置的,这样一来就会出现不同名称的标签表达同一意思的情况。一个最典型的例子就是「动态规划」和「DP」这两个标签。

需求

将题目标签系统修改为类似 LibreOJ 的标签系统。附图:

▲ 标签管理入口

▲ 标签管理界面

注:无需实现多语言功能。

实现细节

tags

键名 类型
id int NOT NULL AUTO_INCREMENT
name varchar(30) NOT NULL

problems_tags

键名 类型
id int NOT NULL AUTO_INCREMENT
problem_id int NOT NULL
tag_id int NOT NULL

关于增加审计日志功能的构想

背景

在 S2OJ 的使用过程中,有一些敏感操作是不会记录操作者信息的。随着题目管理员数量的日渐增加,增加审计日志的必要性在日渐提升。

需求

为 S2OJ 增加审计日志功能。

实现细节

数据表

新增:audit_logs

列名 数据类型 说明
username varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL 用户名
type varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL 记录类型
target_id int NOT NULL 对应项目的 ID
time datetime DEFAULT CURRENT_TIMESTAMP 时间
remote_addr varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL remote_addr
http_x_forwarded_for varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL http_x_forwarded_for
detail json NOT NULL 详情

记录类型

TODO

Remote Judge 功能

背景

在教学过程中,经常会遇到同一题单中的题目在不同 Online Judge 上的情况。此类情况一般使用 Vjudge 解决,但 Vjudge 无法添加校内 OJ 上的题目,因此只能在不同的网站上来回切换完成教学、学习任务,存在一定不便。

需求

为 S2OJ 实现 Remote Judge 功能,并将其集成进以下模块中:

  • 比赛
    支持在比赛中使用 Remote Judge 题库中的题目。
  • 题库
    单独开辟几个板块列出每个 Remote Judge 题库中的所有题目。
    支持为 Remote Judge 题库中的题目添加题解。
  • 题单
    支持在题单中添加来自 Remote Judge 题库的题目。
    支持在小组作业中显示包含来自 Remote Judge 题库的题目。

需要支持以下 Online Judge:

  • Codeforces
  • AtCoder
  • LibreOJ
  • UniversalOJ

架构简述

编写一个 Node 脚本,支持以下操作:

  • 登录远端题库账号。
    如果远端题库存在验证码,考虑进行机器识别或者申请免验证账号(如 LibreOJ)。
  • 从 Web 端抓取最新的评测记录并提交至远端。
    提交时需要多次重试,以防由于网络问题导致的提交失败。多次提交失败后需要将 Web 端的状态设置为 Judgement Failed
  • 从远端抓取评测记录的状态信息,并反馈至 Web 端。
    抓取时需要定时更新直至评测完毕,期间数据需要实时反馈至 Web 端。抓取频率不宜过高。
    抓取时还需判断提交记录对应是否正确。参考洛谷的实现,可以在代码的起始部分增加 // S2OJ_SUBMISSION_ID: xxxxxx 作为识别。
    为防止网络等问题导致的请求失败,需要设置超时时间,超时后将 Web 端的状态设置为 Judgement Failed

此外,还需要对各个题库做针对性地适配,对接其网站上的相关接口。

在 Web 端,需要进行以下修改:

  • 增加存储远程题库的数据表,并新增相关前后端代码。
  • 在比赛、题单中增加引用题库类型指定,并修改相关前后端代码。

以及一些其他杂项的修改。

参考实现

关于新的权限管理的构想

背景

当前 S2OJ 的权限管理虽能满足基本需求,但当部分情况下需要灵活管理权限时则会遇到诸多问题。一个典型的案例是在正常情况下,外校学生不应当能查看非自己参加过的比赛的题目,并且参赛需要老师为其手动报名,不能自行点击「报名」按钮报名。当前对这个功能的实现过于丑陋,同时也不具备良好的可扩展性。

需求

为 S2OJ 实现一个灵活的、可扩展的权限管理模型。

本 Issue 将作为此构想的备忘录。

实现细节

数据表

user_info

该表中现有的 usertype 字段将只存在以下几个值:

  • student 学生账号
  • teacher 老师账号
  • banned 封禁账号
  • system 系统账号(root,std)

其余权限将存放在 PR #14 中引入的 extra 字段中,使用 $.permissions 读取。

权限详情

题目 problems

  • 查看、提交题目 problems.view
  • 创建题目 problems.create
  • 下载测试数据 problems.download_testdata
  • 管理题目 problems.manage
    • 编辑题面、更新数据
    • 修改题目管理者
    • 重测提交记录(单条、批量)
    • 删除提交记录

比赛 contests

  • 查看比赛列表 contests.view(若无权限则只显示已参加过的比赛列表)
  • 报名比赛 contests.register
  • 创建比赛 contests.create
  • 开始最终测试 contests.start_final_test
  • 管理比赛 contests.manage
    • 标题、起止时间、题目
    • 问答、公告
    • 终榜
    • 修改比赛管理者

题单 lists

  • 查看题单 lists.view(关闭后无法查看题单列表及详情)
  • 创建题单 lists.create
  • 编辑题单 lists.manage
    • 标题、题目
    • 修改题单管理者 (暂无此功能)

小组 groups

  • 查看小组 groups.view(若无此权限则只能查看所在的小组)
  • 创建小组 groups.create
  • 管理小组 groups.manage
    • 标题、公告
    • 用户
    • 作业
    • 修改小组管理者 (暂无此功能)

博客 blogs

  • 查看博客 blogs.view(若无此权限只能查看自己创建的博客)
  • 创建博客 blogs.create
    • 以自己的身份创建博客(默认)
    • 以他人的身份创建博客(仅限超级用户)
  • 管理博客 blogs.manage
    • 修改博客内容
    • 删除博客

用户 users

  • 查看用户信息 users.view
  • 上传图片 users.upload_image

系统

仅限超级用户。

  • 首页管理
    • 公告
    • 倒计时
    • 常用链接
  • 用户管理
    • 新增用户
    • 重置密码
    • 修改用户类别和权限(仅限超级用户)
  • 图床管理
    • 查看全部图片列表
    • 删除图片

最终测试时直接拉取赛时评测结果

实现

  • 如果赛时评测记录已存在「终测结果」,则直接将新评测记录的测试结果设置为该结果。
  • 如果赛时评测记录未存在「终测结果」,则直接调用 UOJSubmission::rejudgeById() 进行重测。

比赛中途报名参赛

背景

在日常训练中,经常会出现自己忘了报名比赛或者老师批量报名时遗漏的情况,这在老师不在场或者不便联系老师时会带来一些麻烦。

需求

允许选手在比赛的中途报名参赛。

本 Issue 作为此需求的备忘录。

实现细节

1227acf

关于Mathjax和KaTeX的选择

背景

今天打比赛发现网有点慢,结果就是Mathjax的加载速度很慢,有的时候刷新好几次等上几分钟也渲染不出来,上午刚给自己的博客从 Mathjax 换到 KaTeX 无斜体版本,发现契合度和 Mathjax 根本不是一个量级,在同样差的网络下, Mathjax 会在打开几秒后才渲染成功, KaTeX 能做到在网页加载成功的同时渲染完成。
效果预览
(因为 hexo 渲染器的问题一些公式没有被渲染,但是使用 KaTeX script 在本地能够全部渲染成功)

需求

用 KaTeX 替代 S2OJ 中的 Mathjax,作为 markdown LaTeX 公式的渲染器

实现细节

不太会前端,还在研究怎么改

目前的想法是把 requirelib 含有 mathjax 的全部改成katex,然后添加 katex.min.css katex.min.js auto-render.min.js 与渲染规则(可以直接从网上照搬)
markdown editor 先不动(我看不懂),先继续使用 mathjax,修改为 katex 可以参考 markdown all-in-one 的实现
我已经做了改动,但是部署镜像之后网页端跑不起来 (archlinux),所以没法测试,您可以看我 fork 的仓库的修改

Remote Judge: 洛谷

实现思路

引导用户前往 洛谷 上手动提交代码,然后提交以下信息:

  1. Cookie 中的 _uid__clientid
  2. 提交记录 ID。

然后通过 https://www.luogu.com.cn/record/{id}?_contentOnly=1 获取信息,所需内容结构如下:

{
    "code": 200,
    "currentTemplate": "RecordShow",
    "currentData": {
        "record": {
            "detail": {
                "compileResult": {
                    "success": true,
                    "message": null
                },
                "judgeResult": {
                    "subtasks": [
                        {
                            "id": 0,
                            "score": 100,
                            "status": 12,
                            "testCases": [
                                {
                                    "id": 0,
                                    "status": 12,
                                    "time": 28,
                                    "memory": 5976,
                                    "score": 20,
                                    "signal": 0,
                                    "exitCode": 0,
                                    "description": "ok accepted",
                                    "subtaskID": 0
                                },
                                {
                                    "id": 1,
                                    "status": 12,
                                    "time": 57,
                                    "memory": 7116,
                                    "score": 20,
                                    "signal": 0,
                                    "exitCode": 0,
                                    "description": "ok accepted",
                                    "subtaskID": 0
                                },
                                {
                                    "id": 2,
                                    "status": 12,
                                    "time": 92,
                                    "memory": 7772,
                                    "score": 20,
                                    "signal": 0,
                                    "exitCode": 0,
                                    "description": "ok accepted",
                                    "subtaskID": 0
                                },
                                {
                                    "id": 3,
                                    "status": 12,
                                    "time": 127,
                                    "memory": 9292,
                                    "score": 20,
                                    "signal": 0,
                                    "exitCode": 0,
                                    "description": "ok accepted",
                                    "subtaskID": 0
                                },
                                {
                                    "id": 4,
                                    "status": 12,
                                    "time": 129,
                                    "memory": 9680,
                                    "score": 20,
                                    "signal": 0,
                                    "exitCode": 0,
                                    "description": "ok accepted",
                                    "subtaskID": 0
                                }
                            ],
                            "time": 433,
                            "memory": 9680
                        }
                    ],
                    "finishedCaseCount": 5,
                    "status": 0,
                    "time": 0,
                    "memory": 0,
                    "score": 0
                }
            },
            "sourceCode": "",
            "time": 0,
            "memory": 0,
            "problem": {
                "pid": "",
                "fullScore": 100
            },
            "sourceCodeLength": 3892,
            "submitTime": 1675255767,
            "language": 11,
            "user": {
                "uid": 168214
            },
            "id": 101128189,
            "status": 12,
            "enableO2": true,
            "score": 100
        },
        "testCaseGroup": [[0, 1, 2, 3, 4]],
        "showStatus": true
    },
    "currentTime": 1675333702,
    "currentUser": {
        "uid": 168214
    }
}

解析,并转换为 UOJ 格式。

remote-judger.development.env 不存在

执行 docker-compose -f docker-compose.development.yml up -d --build 报错:
Failed to load remote-judger.development.env: open remote-judger.development.env: no such file or directory.

关于增加图床功能的提议

概述

在 OJ 的使用过程中经常会遇到需要上传图片的情况,目前的解决方案是上传至外部图床,但存在失效风险,因此需要一个内建的图床来保证图片在 OJ 的存续期间一直有效。

解决方案

为 S2OJ 增加图床功能。

功能设计

在顶栏增加「应用」下拉菜单,在下拉菜单中显示图床入口。

权限控制

  • 禁止游客上传图片;
  • 图片大小限制(5 MB);
  • 用户图片总大小限制(单用户 100 MB,管理员可在管理页面提升限制)。

路由列表

  • GET /image_hosting/:name.png 获取图片
    • 限制跨域请求
  • GET & POST /image_hosting 图片浏览 & 上传
    • 未登录用户返回 403
    • 上传图片时转码为 png 格式并在右下角添加字样为 UOJConfig::$data['profile']['short-name'] 的水印
    • 转码后计算大小限制,超出限制返回错误
    • 允许删除自己上传的图片
  • GET & POST /super-manage/image_hosting 图床管理
    • 删除用户图片

数据库

新表:users_images

列名 值类型 描述
id int(11) ID
filename varchar(100) 图片存储文件名
uploader varchar(20) 上传者的用户名
width int(11) 宽度(单位:像素)
height int(11) 高度(单位:像素)
upload_time datetime 上传时间
size int(11) 大小(单位:Byte)
hash varchar(70) 文件哈希值

已存在表:user_info

新列 值类型 描述
images_size_limit int(11) 图片上传总大小限制(单位:Byte)

参考资源

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.