Go to file
Himit_ZH 26c16b2b64 更新部署文档 2021-05-01 10:50:24 +08:00
docs 更新部署文档 2021-05-01 10:50:24 +08:00
hoj-springboot 更新部署文档 2021-05-01 10:50:24 +08:00
hoj-vue 更新部署文档 2021-05-01 10:50:24 +08:00
judger 架构更新,上线部署 2021-04-13 12:59:57 +08:00
sqlAndsetting 加入题目模板,修改页面页脚 2021-04-24 19:59:56 +08:00
LICENSE 判题调度逻辑2.0解决并发问题 2021-04-15 23:31:30 +08:00
README.md 加入题目模板,修改页面页脚 2021-04-24 19:59:56 +08:00

README.md

一、介绍

基于前后端分离分布式架构的在线测评平台hoj

在线Demohttp://www.hcode.top

上线日记

时间 内容 更新者
2020-10-26 正式开发 Himit_ZH
2021-04-10 首次上线测试 Himit_ZH
2021-04-15 判题调度2.0解决并发问题 Himit_ZH
2021-04-16 重构解耦JudgeServer判题逻辑添加部署文档 Himit_ZH
2021-04-19 加入rsync实现评测数据同步修复一些已知的BUG Himit_ZH
2021-04-24 加入题目模板,修改页面页脚 Himit_ZH

二、部署

注意比较适用于熟悉springbootdocker的开发人员打包部署

部署文档:https://gitee.com/himitzh0730/hoj/tree/master/docs

简略介绍

  • 前端:
    • 技术以Vue为主element-ui为主要框架网站风格样式模仿qdoj
    • 支持手机端,响应式布局
    • 以CodeMirror作为在线代码编辑器
    • 以Mavon-Editor作为富文本编辑器
    • 支持用户头像上传可选择性获取用户Codeforces分数
    • 定时获取例如Codeforces等其它知名OJ的近期比赛数据
    • 当前支持HDU的Virtual Judge远程虚拟判题与题目获取
    • 题目支持特别判题
    • 题目支持可选择性去除提交代码的末尾空白符会影响CE判定
    • 题目支持可选择性允许用户查看各个测试点结果状态运行时间运行空间OI题目的测试点得分暂不支持测试点数据公开。
    • 管理后台支持题目数据以ZIP上传或手动输入上传
    • 管理后台支持监控服务系统的状态及各判题服务的状态
    • 管理后台支持动态修改网站配置,例如邮件系统配置,数据库配置等
    • 比赛支持封榜支持ACM与OI模式
    • 比赛支持私有赛(需要密码才可查看与提交),保护赛(每个用户都可查看,提交需要密码),公开赛(每个用户都可查看与提交)三种模式
    • 用户提交失败时可重新提交,管理员支持提交重判与比赛题目所有提交重判
    • ......
  • 后端:
    • Web框架技术以Springboot为主
    • 以Nacos为分布式注册中心及分布式配置中心支持配置文件动态刷新支持判题服务Ribbon的负载均衡
    • 以Mybatis-Plus为数据库中间件负责数据实体类与数据库数据的转化与获取。
    • 以Jsoup为爬虫框架负责远程虚拟OJ的题目获取及提交结果获取同时定时获取各用户的Codeforces分数以及其它知名OJ的近期比赛。
    • 以Shiro为安全框架支持用户角色权限管理支持token刷新
    • 以redis的发布订阅者作为判题服务的消息提醒以此调用判题服务
    • 后端分为数据后台服务DataBackup及判题服务JudgeServer
      1. 数据后台服务:负责提供接口,提供相关数据给前端等
      2. 判题服务只负责获取数据后台服务传输过来的判题的提交调用VJ判题或调用判题机Go-Judge进行评测将对应结果写回数据库
  • 判题机:
    • 支持HDU的VJ判题
    • 支持Codefoces的VJ判题
    • 以HttpAPI的形式调用Go-Jugde(高性能可复用的判题沙盒)判题安全沙盒进行提交程序的评测(调用线程池多线程跑评测)
  • 数据库
    • Mysql
  • 缓存中间件
    • Redis

二、系统架构

总概四大系统

  1. 前端vue页面显示系统

  2. 数据交互后台系统

  3. 判题服务系统

  4. 爬虫系统

判题逻辑概述

  1. 前端用户提交数据。
  2. 后端数据服务DataBackup获取到数据先将提交数据初始化同时将该提交的状态变成等待中写入数据库。
  3. 通过Redis写入等待判题队列
  4. 调用work处理者初始化传输数据使用springcloud alibaba通过nacos注册中心调用判题微服务。
  5. 若是调用判题服务失败(没有空闲的判题服务器),则重新通过发布者将该提交信息发布到对应等待判题队列重回3。
  6. 若是调用失败超过30次则将提交的状态修改为提交失败不再进行判题服务的调用。
  7. 前端用户可看到提交变成提交失败可点击状态进行重新提交重回2重新提交不影响提交时间等数据
  8. 判题微服务获取到提交数据:
    • 若是远程调用进行远程提交获取对应的提交ID若是获取失败则判为提交失败若是获取成功就启用线程定时器每2秒根据提交ID获取判题结果。

      定时尝试30次获取成功写回数据库获取失败就修改此次提交为提交失败。

    • 若是自家题目提交则启用线程池多线程使用Http将对应测试点数据与代码提交给Go-Judge判题沙盒进行编译与评测最后获取各个评测点结果进行结果计算写回数据库。

HOJ基本逻辑架构图

image-20201030234527577

springcloud alibaba 分布式微服务架构图

Consumer后台数据交互服务

Provider判题服务

Nacos注册中心Consumer通过nacos调用Provider

spingcloud-Alibaba.png

三、网站部分截图

首页页面

hoj1

题目列表页

hoj2

题目详情页

hoj7

比赛列表页

hoj3

比赛详情首页

hoj4

排行榜

hoj9

个人信息页

hoj6

个人设置页

hoj8

管理后台首页

hoj5

部分手机端显示

hojmb1

hojmb2

四、特判程序例子

#include<iostream>
#include<cstdio>
#define AC 100
#define WA 101
#define ERROR 102
using namespace std;


int spj(int user_output, FILE *output);

void close_file(FILE *f){
    if(f != NULL){
        fclose(f);
    }
}

int main(int argc, char *args[]){
    FILE *output;
    int result;
    if(argc != 2){
        return ERROR;
    }
    int user_output;
    cin>>user_output;
    cout<<user_output<<endl;
    output = fopen(args[1], "r");
	
    result = spj(user_output, output);
    printf("result: %d\n", result);
    
    close_file(output);
    return result;
}

int spj(int user_output, FILE *output){
    /*
      parameter: 
        - output标程输出文件的指针
        - user_output用户输出数据
      return: 
        - 如果用户答案正确返回AC
        - 如果用户答案错误返回WA
        - 如果主动捕获到自己的错误如内存分配失败返回ERROR
      */
      int std_out;
      while(fscanf(output, "%d", &std_out) != EOF){
          if(user_output+1 != std_out){
             cout<<user_output<<endl<<std_out;
              return WA;
          }
      }
      return AC;
}

五、附加:

数据库表内容及API文档

Go-Sanbox API文档

go-judge