From 208975c78017e7d996faaf685cd8cea6e6460ece Mon Sep 17 00:00:00 2001 From: github-actions <> Date: Sat, 30 Oct 2021 13:36:09 +0000 Subject: [PATCH] Google Java Format --- .../application/ApplicationBootstrap.java | 291 ++- .../application/ApplicationDispatcher.java | 627 +++--- .../application/ApplicationHeartbeat.java | 188 +- .../voj/judger/core/Comparator.java | 264 +-- .../verwandlung/voj/judger/core/Compiler.java | 233 +-- .../voj/judger/core/Dispatcher.java | 437 ++-- .../voj/judger/core/Preprocessor.java | 295 ++- .../verwandlung/voj/judger/core/Runner.java | 421 ++-- .../exception/CreateDirectoryException.java | 64 +- .../exception/IllgealSubmissionException.java | 62 +- .../voj/judger/mapper/CheckpointMapper.java | 70 +- .../voj/judger/mapper/JudgeResultMapper.java | 90 +- .../voj/judger/mapper/LanguageMapper.java | 132 +- .../voj/judger/mapper/ProblemMapper.java | 84 +- .../voj/judger/mapper/SubmissionMapper.java | 113 +- .../voj/judger/mapper/UserGroupMapper.java | 65 +- .../voj/judger/mapper/UserMapper.java | 77 +- .../voj/judger/messenger/MessageReceiver.java | 122 +- .../voj/judger/messenger/MessageSender.java | 62 +- .../voj/judger/model/Checkpoint.java | 367 ++-- .../voj/judger/model/JudgeResult.java | 211 +- .../voj/judger/model/Language.java | 346 ++-- .../verwandlung/voj/judger/model/Problem.java | 680 +++--- .../voj/judger/model/Submission.java | 671 +++--- .../verwandlung/voj/judger/model/User.java | 399 ++-- .../voj/judger/model/UserGroup.java | 207 +- .../voj/judger/util/DigestUtils.java | 184 +- .../voj/judger/util/NativeLibraryLoader.java | 121 +- .../voj/judger/core/ComparatorTest.java | 220 +- .../voj/judger/core/CompilerTest.java | 160 +- .../voj/judger/core/PreprocessorTest.java | 131 +- .../voj/judger/core/RunnerTest.java | 180 +- .../judger/mapper/CheckpointMapperTest.java | 91 +- .../judger/mapper/JudgeResultMapperTest.java | 89 +- .../voj/judger/mapper/LanguageMapperTest.java | 157 +- .../voj/judger/mapper/ProblemMapperTest.java | 86 +- .../judger/mapper/SubmissionMapperTest.java | 86 +- .../judger/mapper/UserGroupMapperTest.java | 87 +- .../voj/judger/mapper/UserMapperTest.java | 87 +- .../voj/web/aspect/InterceptorAspect.java | 295 +-- .../voj/web/aspect/ViewAspect.java | 292 +-- .../web/controller/AccountsController.java | 890 ++++---- .../controller/AdministrationController.java | 1825 +++++++++-------- .../web/controller/ContestsController.java | 453 ++-- .../voj/web/controller/DefaultController.java | 494 +++-- .../web/controller/DiscussionController.java | 830 ++++---- .../ExceptionHandlingController.java | 164 +- .../web/controller/ProblemsController.java | 512 ++--- .../web/controller/SubmissionController.java | 353 ++-- .../exception/ResourceNotFoundException.java | 42 +- .../mapper/BulletinBoardMessageMapper.java | 119 +- .../voj/web/mapper/CheckpointMapper.java | 93 +- .../web/mapper/ContestContestantMapper.java | 149 +- .../voj/web/mapper/ContestMapper.java | 115 +- .../web/mapper/ContestSubmissionMapper.java | 126 +- .../voj/web/mapper/DiscussionReplyMapper.java | 105 +- .../web/mapper/DiscussionThreadMapper.java | 125 +- .../voj/web/mapper/DiscussionTopicMapper.java | 106 +- .../voj/web/mapper/EmailValidationMapper.java | 77 +- .../voj/web/mapper/JudgeResultMapper.java | 66 +- .../voj/web/mapper/LanguageMapper.java | 118 +- .../voj/web/mapper/OptionMapper.java | 90 +- .../voj/web/mapper/ProblemCategoryMapper.java | 182 +- .../voj/web/mapper/ProblemMapper.java | 219 +- .../voj/web/mapper/ProblemTagMapper.java | 176 +- .../voj/web/mapper/SubmissionMapper.java | 372 ++-- .../voj/web/mapper/UserGroupMapper.java | 79 +- .../voj/web/mapper/UserMapper.java | 219 +- .../voj/web/mapper/UserMetaMapper.java | 127 +- .../messenger/ApplicationEventListener.java | 334 ++- .../voj/web/messenger/KeepAliveEvent.java | 143 +- .../voj/web/messenger/MessageReceiver.java | 321 +-- .../voj/web/messenger/MessageSender.java | 78 +- .../voj/web/messenger/SubmissionEvent.java | 172 +- .../voj/web/model/BulletinBoardMessage.java | 283 +-- .../verwandlung/voj/web/model/Checkpoint.java | 367 ++-- .../verwandlung/voj/web/model/Contest.java | 452 ++-- .../voj/web/model/ContestContestant.java | 347 ++-- .../voj/web/model/ContestSubmission.java | 151 +- .../voj/web/model/DiscussionReply.java | 393 ++-- .../voj/web/model/DiscussionThread.java | 429 ++-- .../voj/web/model/DiscussionTopic.java | 297 +-- .../voj/web/model/EmailValidation.java | 207 +- .../voj/web/model/JudgeResult.java | 211 +- .../verwandlung/voj/web/model/Language.java | 348 ++-- .../org/verwandlung/voj/web/model/Option.java | 287 ++- .../verwandlung/voj/web/model/Problem.java | 817 ++++---- .../voj/web/model/ProblemCategory.java | 315 ++- .../model/ProblemCategoryRelationship.java | 311 +-- .../verwandlung/voj/web/model/ProblemTag.java | 278 ++- .../voj/web/model/ProblemTagRelationship.java | 308 ++- .../verwandlung/voj/web/model/Submission.java | 754 +++---- .../org/verwandlung/voj/web/model/User.java | 438 ++-- .../verwandlung/voj/web/model/UserGroup.java | 207 +- .../verwandlung/voj/web/model/UserMeta.java | 287 ++- .../voj/web/service/BulletinBoardService.java | 96 +- .../voj/web/service/ContestService.java | 682 +++--- .../voj/web/service/DiscussionService.java | 1198 ++++++----- .../voj/web/service/LanguageService.java | 628 +++--- .../voj/web/service/OptionService.java | 373 ++-- .../voj/web/service/ProblemService.java | 1475 +++++++------ .../voj/web/service/SubmissionService.java | 728 +++---- .../voj/web/service/UserService.java | 1581 +++++++------- .../voj/web/util/CsrfProtector.java | 155 +- .../verwandlung/voj/web/util/DateUtils.java | 73 +- .../verwandlung/voj/web/util/DigestUtils.java | 115 +- .../voj/web/util/HtmlTextFilter.java | 81 +- .../voj/web/util/HttpRequestParser.java | 68 +- .../voj/web/util/HttpSessionParser.java | 107 +- .../verwandlung/voj/web/util/LocaleUtils.java | 96 +- .../verwandlung/voj/web/util/MailSender.java | 210 +- .../voj/web/util/OffensiveWordFilter.java | 499 +++-- .../voj/web/util/SessionListener.java | 126 +- .../voj/web/util/SlugifyUtils.java | 98 +- .../voj/web/mapper/CheckpointMapperTest.java | 190 +- .../mapper/ContestContestantMapperTest.java | 391 ++-- .../voj/web/mapper/ContestMapperTest.java | 405 ++-- .../web/mapper/DiscussionReplyMapperTest.java | 256 ++- .../mapper/DiscussionThreadMapperTest.java | 544 +++-- .../web/mapper/DiscussionTopicMapperTest.java | 364 ++-- .../web/mapper/EmailValidationMapperTest.java | 235 +-- .../voj/web/mapper/JudgeResultMapperTest.java | 134 +- .../voj/web/mapper/LanguageMapperTest.java | 315 ++- .../voj/web/mapper/OptionMapperTest.java | 171 +- .../web/mapper/ProblemCategoryMapperTest.java | 591 +++--- .../voj/web/mapper/ProblemMapperTest.java | 464 ++--- .../voj/web/mapper/ProblemTagMapperTest.java | 548 +++-- .../voj/web/mapper/SubmissionMapperTest.java | 1058 +++++----- .../voj/web/mapper/UserGroupMapperTest.java | 157 +- .../voj/web/mapper/UserMapperTest.java | 511 +++-- .../voj/web/mapper/UserMetaMapperTest.java | 424 ++-- .../voj/web/util/DigestUtilsTest.java | 108 +- .../voj/web/util/HtmlTextFilterTest.java | 71 +- .../voj/web/util/MessageReceiverTest.java | 61 +- .../voj/web/util/MessageSenderTest.java | 71 +- .../voj/web/util/OffensiveWordFilterTest.java | 62 +- .../voj/web/util/SlugifyUtilsTest.java | 68 +- 137 files changed, 20558 insertions(+), 20635 deletions(-) diff --git a/judger/src/main/java/org/verwandlung/voj/judger/application/ApplicationBootstrap.java b/judger/src/main/java/org/verwandlung/voj/judger/application/ApplicationBootstrap.java index e9b11157..3a676bba 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/application/ApplicationBootstrap.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/application/ApplicationBootstrap.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -55,142 +55,127 @@ /** * 程序测评模块的加载器. - * + * * @author Haozhe Xie */ public class ApplicationBootstrap { - /** - * 应用程序入口. - */ - public static void main(String[] args) { - LOGGER.info("Starting Verwandlung Online Judge Judger..."); - ApplicationBootstrap app = new ApplicationBootstrap(); - app.getApplicationContext(); - app.setupHeartBeat(); - app.getSystemEnvironment(); - app.setUpShutdownHook(); - LOGGER.info("Verwandlung Online Judge Judger started."); - } - - /** - * 加载应用程序配置. - */ - private void getApplicationContext() { - applicationContext = new - ClassPathXmlApplicationContext("application-context.xml"); - } - - /** - * 配置与Web模块的心跳连接. - * 定时向Web模块发送Keep-Alive信号. - */ - private void setupHeartBeat() { - final int INITIAL_DELAY = 0; - final int PERIOD = 25; - - ApplicationHeartbeat heartbeat = applicationContext.getBean(ApplicationHeartbeat.class); - ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); - scheduler.scheduleAtFixedRate(heartbeat, INITIAL_DELAY, PERIOD, TimeUnit.MINUTES); - } - - /** - * 设置ShutdownHook. - * 用于完成程序正常退出前的准备工作. - */ - private void setUpShutdownHook() { - final Thread mainThread = Thread.currentThread(); - Runtime.getRuntime().addShutdownHook(new Thread() { - public void run() { - try { - LOGGER.info("Verwandlung Online Judge Judger is shutting down..."); - mainThread.join(); - } catch (InterruptedException ex) { - LOGGER.catching(ex); - } - } - }); - } - - /** - * 获取系统环境变量. - * 以便进行Bug的复现. - */ - private void getSystemEnvironment() { - LOGGER.info("System Information: " ); - LOGGER.info("\tOperating System Name: " + System.getProperty("os.name")); - LOGGER.info("\tOperating System Version: " + System.getProperty("os.version")); - LOGGER.info("\tJava VM Name: " + System.getProperty("java.vm.name")); - LOGGER.info("\tJava Runtime Version: " + System.getProperty("java.runtime.version")); - - LOGGER.info("Compiler Information: " ); - LanguageMapper languageMapper = applicationContext.getBean(LanguageMapper.class); - List languages = languageMapper.getAllLanguages(); - for ( Language language : languages ) { - String languageName = language.getLanguageName(); - String compileProgram = getCompileProgram(language.getCompileCommand()); - LOGGER.info("\t" + languageName + ": " + getCompilerVersion(languageName, compileProgram)); - } - } - - /** - * 获取编译程序的命令行. - * @param compileCommand - 编译命令的命令行 - * @return 编译程序的命令行 - */ - private String getCompileProgram(String compileCommand) { - int firstSpaceIndex = compileCommand.indexOf(" "); - String compileProgram = compileCommand.substring(0, firstSpaceIndex); - - if ( "javac".equalsIgnoreCase(compileProgram) ) { - return "java"; - } - return compileProgram; - } - - /** - * 获取编译器的版本信息. - * @param languageName - 编程语言名称 - * @param compileProgram - 编译所使用的命令 - * @return 编译器的版本信息 - */ - private String getCompilerVersion(String languageName, String compileProgram) { - String versionCommand = getVersionCommand(languageName); - StringBuilder compilerVersion = new StringBuilder(); - - try { - String[] command = { - compileProgram, versionCommand - }; - Process process = Runtime.getRuntime().exec(command); - - compilerVersion.append("Command Line: " + command + "\n"); - compilerVersion.append(IOUtils.toString(process.getInputStream())); - compilerVersion.append(IOUtils.toString(process.getErrorStream())); - } catch ( Exception ex ) { - return "Not Found"; - } - return compilerVersion.toString(); - } - - /** - * 获取编译器版本的命令行参数. - * @param languageName - 编程语言名称 - * @return 获取编译器版本的命令行参数 - */ - private String getVersionCommand(String languageName) { - if ( "Java".equalsIgnoreCase(languageName) ) { - return " -version"; - } - return " --version"; - } - - /** - * 应用程序配置. - */ - private ApplicationContext applicationContext; - - /** - * 日志记录器. - */ - private static final Logger LOGGER = LogManager.getLogger(ApplicationBootstrap.class); + /** 应用程序入口. */ + public static void main(String[] args) { + LOGGER.info("Starting Verwandlung Online Judge Judger..."); + ApplicationBootstrap app = new ApplicationBootstrap(); + app.getApplicationContext(); + app.setupHeartBeat(); + app.getSystemEnvironment(); + app.setUpShutdownHook(); + LOGGER.info("Verwandlung Online Judge Judger started."); + } + + /** 加载应用程序配置. */ + private void getApplicationContext() { + applicationContext = new ClassPathXmlApplicationContext("application-context.xml"); + } + + /** 配置与Web模块的心跳连接. 定时向Web模块发送Keep-Alive信号. */ + private void setupHeartBeat() { + final int INITIAL_DELAY = 0; + final int PERIOD = 25; + + ApplicationHeartbeat heartbeat = applicationContext.getBean(ApplicationHeartbeat.class); + ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + scheduler.scheduleAtFixedRate(heartbeat, INITIAL_DELAY, PERIOD, TimeUnit.MINUTES); + } + + /** 设置ShutdownHook. 用于完成程序正常退出前的准备工作. */ + private void setUpShutdownHook() { + final Thread mainThread = Thread.currentThread(); + Runtime.getRuntime() + .addShutdownHook( + new Thread() { + public void run() { + try { + LOGGER.info("Verwandlung Online Judge Judger is shutting down..."); + mainThread.join(); + } catch (InterruptedException ex) { + LOGGER.catching(ex); + } + } + }); + } + + /** 获取系统环境变量. 以便进行Bug的复现. */ + private void getSystemEnvironment() { + LOGGER.info("System Information: "); + LOGGER.info("\tOperating System Name: " + System.getProperty("os.name")); + LOGGER.info("\tOperating System Version: " + System.getProperty("os.version")); + LOGGER.info("\tJava VM Name: " + System.getProperty("java.vm.name")); + LOGGER.info("\tJava Runtime Version: " + System.getProperty("java.runtime.version")); + + LOGGER.info("Compiler Information: "); + LanguageMapper languageMapper = applicationContext.getBean(LanguageMapper.class); + List languages = languageMapper.getAllLanguages(); + for (Language language : languages) { + String languageName = language.getLanguageName(); + String compileProgram = getCompileProgram(language.getCompileCommand()); + LOGGER.info("\t" + languageName + ": " + getCompilerVersion(languageName, compileProgram)); + } + } + + /** + * 获取编译程序的命令行. + * + * @param compileCommand - 编译命令的命令行 + * @return 编译程序的命令行 + */ + private String getCompileProgram(String compileCommand) { + int firstSpaceIndex = compileCommand.indexOf(" "); + String compileProgram = compileCommand.substring(0, firstSpaceIndex); + + if ("javac".equalsIgnoreCase(compileProgram)) { + return "java"; + } + return compileProgram; + } + + /** + * 获取编译器的版本信息. + * + * @param languageName - 编程语言名称 + * @param compileProgram - 编译所使用的命令 + * @return 编译器的版本信息 + */ + private String getCompilerVersion(String languageName, String compileProgram) { + String versionCommand = getVersionCommand(languageName); + StringBuilder compilerVersion = new StringBuilder(); + + try { + String[] command = {compileProgram, versionCommand}; + Process process = Runtime.getRuntime().exec(command); + + compilerVersion.append("Command Line: " + command + "\n"); + compilerVersion.append(IOUtils.toString(process.getInputStream())); + compilerVersion.append(IOUtils.toString(process.getErrorStream())); + } catch (Exception ex) { + return "Not Found"; + } + return compilerVersion.toString(); + } + + /** + * 获取编译器版本的命令行参数. + * + * @param languageName - 编程语言名称 + * @return 获取编译器版本的命令行参数 + */ + private String getVersionCommand(String languageName) { + if ("Java".equalsIgnoreCase(languageName)) { + return " -version"; + } + return " --version"; + } + + /** 应用程序配置. */ + private ApplicationContext applicationContext; + + /** 日志记录器. */ + private static final Logger LOGGER = LogManager.getLogger(ApplicationBootstrap.class); } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/application/ApplicationDispatcher.java b/judger/src/main/java/org/verwandlung/voj/judger/application/ApplicationDispatcher.java index 28e59ce9..0d8682fb 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/application/ApplicationDispatcher.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/application/ApplicationDispatcher.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -58,300 +58,307 @@ /** * 应用程序调度器. - * + * * @author Haozhe Xie */ @Component public class ApplicationDispatcher { - /** - * 收到消息队列的新的评测请求时的回调函数. - * @param submissionId - 评测记录的唯一标识符 - */ - public void onSubmissionCreated(long submissionId) { - try { - judgerDispatcher.createNewTask(submissionId); - } catch (Exception ex) { - LOGGER.catching(ex); - } - } - - /** - * 当系统错误发生时通知用户. - * @param submissionId - 评测记录的唯一标识符 - */ - public void onErrorOccurred(long submissionId) { - updateSubmission(submissionId, 0, 0, 0, "SE", "Internal error occured."); - - Map mapMessage = new HashMap<>(); - mapMessage.put("event", "ErrorOccurred"); - mapMessage.put("submissionId", submissionId); - - messageSender.sendMessage(mapMessage); - } - - /** - * 当编译阶段结束时通知用户. - * @param submissionId - 评测记录的唯一标识符 - * @param result - 编译结果 - */ - public void onCompileFinished(long submissionId, Map result) { - boolean isSuccessful = (Boolean)result.get("isSuccessful"); - String log = log = getJudgeLog(result); - - if ( !isSuccessful ) { - updateSubmission(submissionId, 0, 0, 0, "CE", log); - } - Map mapMessage = new HashMap<>(); - mapMessage.put("event", "CompileFinished"); - mapMessage.put("submissionId", submissionId); - mapMessage.put("isSuccessful", isSuccessful); - mapMessage.put("log", log); - - messageSender.sendMessage(mapMessage); - } - - /** - * 实时返回评测结果. - * @param submissionId - 提交记录的编号 - * @param checkpointId - 测试点的编号 - * @param runtimeResult - 某个测试点的程序运行结果 - */ - public void onOneTestPointFinished(long submissionId, int checkpointId, Map runtimeResult) { - String runtimeResultSlug = getRuntimeResultSlug(runtimeResult); - String runtimeResultName = getRuntimeResultName(runtimeResultSlug); - int usedTime = getUsedTime(runtimeResult); - int usedMemory = getUsedMemory(runtimeResult); - int score = getScore(runtimeResult); - - Map mapMessage = new HashMap<>(); - mapMessage.put("event", "TestPointFinished"); - mapMessage.put("submissionId", submissionId); - mapMessage.put("checkpointId", checkpointId); - mapMessage.put("runtimeResult", runtimeResultName); - mapMessage.put("usedTime", usedTime); - mapMessage.put("usedMemory", usedMemory); - mapMessage.put("score", score); - - messageSender.sendMessage(mapMessage); - } - - /** - * 持久化程序评测结果 - * @param submissionId - 提交记录的编号 - * @param runtimeResults - 对各个测试点的评测结果集 - */ - public void onAllTestPointsFinished(long submissionId, List> runtimeResults) { - int totalTime = 0; - int maxMemory = 0; - int totalScore = 0; - String runtimeResultSlug = "AC"; - String log = "System Error."; - - for ( Map runtimeResult : runtimeResults ) { - String currentRuntimeResultSlug = getRuntimeResultSlug(runtimeResult); - int usedTime = getUsedTime(runtimeResult); - int usedMemory = getUsedMemory(runtimeResult); - int score = getScore(runtimeResult); - - totalTime += usedTime; - if ( usedMemory > maxMemory ) { - maxMemory = usedMemory; - } - if ( "AC".equals(currentRuntimeResultSlug) ) { - totalScore += score; - } - if ( !"AC".equals(currentRuntimeResultSlug) ) { - runtimeResultSlug = currentRuntimeResultSlug; - } - } - log = getJudgeLog(runtimeResults, runtimeResultSlug, totalTime, maxMemory, totalScore); - updateSubmission(submissionId, totalTime, maxMemory, totalScore, runtimeResultSlug, log); - - Map mapMessage = new HashMap<>(); - mapMessage.put("event", "AllTestPointsFinished"); - mapMessage.put("submissionId", submissionId); - mapMessage.put("runtimeResult", getRuntimeResultName(runtimeResultSlug)); - mapMessage.put("totalTime", totalTime); - mapMessage.put("maxMemory", maxMemory); - mapMessage.put("totalScore", totalScore); - - messageSender.sendMessage(mapMessage); - } - - /** - * 从评测结果集中获取程序评测结果的唯一英文缩写. - * @param runtimeResult - 程序评测结果 - * @return 程序评测结果的唯一英文缩写 - */ - private String getRuntimeResultSlug(Map runtimeResult) { - Object runtimeResultObject = runtimeResult.get("runtimeResult"); - - if ( runtimeResultObject == null ) { - return "SE"; - } - return (String)runtimeResultObject; - } - - /** - * 获取评测结果的全称. - * @param runtimeResultSlug - 评测结果的唯一英文缩写 - * @return 评测结果的全称 - */ - private String getRuntimeResultName(String runtimeResultSlug) { - JudgeResult judgeResult = judgeResultMapper.getJudgeResultUsingSlug(runtimeResultSlug); - - if ( judgeResult == null ) { - return "System Error"; - } - return judgeResult.getJudgeResultName(); - } - - /** - * 从评测结果集中获取程序运行时间(ms). - * @param runtimeResult - 程序评测结果 - * @return 程序运行时间(ms) - */ - private int getUsedTime(Map runtimeResult) { - Object usedTimeObject = runtimeResult.get("usedTime"); - - if ( usedTimeObject == null ) { - return 0; - } - return (Integer)usedTimeObject; - } - - /** - * 从评测结果集中获取内存使用量(KB). - * @param runtimeResult - 程序评测结果 - * @return 内存使用量(KB) - */ - private int getUsedMemory(Map runtimeResult) { - Object usedMemoryObject = runtimeResult.get("usedMemory"); - - if ( usedMemoryObject == null ) { - return 0; - } - return (Integer)usedMemoryObject; - } - - /** - * 从评测结果集中获取测试点对应的分值 - * @param runtimeResult - 程序评测结果 - * @return 测试点对应的分值 - */ - private int getScore(Map runtimeResult) { - Object scoreObject = runtimeResult.get("score"); - - if ( scoreObject == null ) { - return 0; - } - return (Integer)scoreObject; - } - - /** - * 格式化编译时日志. - * @param result - 包含编译状态的Map对象 - * @return 格式化后的日志 - */ - private String getJudgeLog(Map result) { - boolean isSuccessful = (Boolean)result.get("isSuccessful"); - String compileLog = (String)result.get("log"); - - StringBuilder formatedLogBuilder = new StringBuilder(); - formatedLogBuilder.append(String.format("Compile %s.\n\n", new Object[] { isSuccessful ? "Successful" : "Error" })); - if ( !isSuccessful ) { - formatedLogBuilder.append(compileLog.replace("\n", "\n\n")); - formatedLogBuilder.append("\nCompile Error, Time = 0 ms, Memory = 0 KB, Score = 0.\n"); - } - return formatedLogBuilder.toString(); - } - - /** - * 格式化运行时日志. - * @param runtimeResults - 对各个测试点的评测结果集 - * @param runtimeResultSlug - * @param totalTime - * @param maxMemory - * @param totalScore - * @return - */ - private String getJudgeLog(List> runtimeResults, - String runtimeResultSlug, int totalTime, int maxMemory, int totalScore) { - int checkpointId = -1; - String runtimeResultName = getRuntimeResultName(runtimeResultSlug); - - StringBuilder formatedLogBuilder = new StringBuilder(); - formatedLogBuilder.append("Compile Successfully.\n\n"); - for ( Map runtimeResult : runtimeResults ) { - String currentRuntimeResultSlug = getRuntimeResultSlug(runtimeResult); - String currentRuntimeResultName = getRuntimeResultName(currentRuntimeResultSlug); - int usedTime = getUsedTime(runtimeResult); - int usedMemory = getUsedMemory(runtimeResult); - int score = getScore(runtimeResult); - - if ( !"AC".equals(currentRuntimeResultSlug) ) { - score = 0; - } - formatedLogBuilder.append(String.format("- Test Point #%d: %s, Time = %d ms, Memory = %d KB, Score = %d\n", - new Object[] { ++ checkpointId, currentRuntimeResultName, usedTime, usedMemory, score })); - } - formatedLogBuilder.append(String.format("\n%s, Time = %d ms, Memory = %d KB, Score = %d\n", - new Object[] { runtimeResultName, totalTime, maxMemory, totalScore })); - return formatedLogBuilder.toString(); - } - - /** - * 更新提交记录信息. - * @param submissionId - 提交记录的唯一标识符 - * @param usedTime - 提交运行使用时间(所有时间之和) - * @param usedMemory - 提交运行使用内存(最大内存占用) - * @param score - 运行得分 - * @param judgeResult - 运行结果(JudgeResultSlug) - * @param log - 运行日志记录 - */ - private void updateSubmission(long submissionId, int usedTime, - int usedMemory, int score, String judgeResult, String log) { - Submission submission = submissionMapper.getSubmission(submissionId); - submission.setExecuteTime(new Date()); - submission.setUsedTime(usedTime); - submission.setUsedMemory(usedMemory); - submission.setJudgeScore(score); - submission.setJudgeResultSlug(judgeResult); - submission.setJudgeLog(log); - - submissionMapper.updateSubmission(submission); - } - - /** - * 自动注入的Dispatcher对象. - * 用于完成评测作业的任务调度. - */ - @Autowired - private Dispatcher judgerDispatcher; - - /** - * 自动注入的MessageSender对象. - * 用于向消息队列发送消息. - */ - @Autowired - private MessageSender messageSender; - - /** - * 自动注入的SubmissionMapper对象. - * 用于查询/更新提交记录的相关信息. - */ - @Autowired - private SubmissionMapper submissionMapper; - - /** - * 自动注入的JudgeResultMapper对象. - * 用于全部评测结果的信息. - */ - @Autowired - private JudgeResultMapper judgeResultMapper; - - /** - * 日志记录器. - */ - private static final Logger LOGGER = LogManager.getLogger(ApplicationDispatcher.class); + /** + * 收到消息队列的新的评测请求时的回调函数. + * + * @param submissionId - 评测记录的唯一标识符 + */ + public void onSubmissionCreated(long submissionId) { + try { + judgerDispatcher.createNewTask(submissionId); + } catch (Exception ex) { + LOGGER.catching(ex); + } + } + + /** + * 当系统错误发生时通知用户. + * + * @param submissionId - 评测记录的唯一标识符 + */ + public void onErrorOccurred(long submissionId) { + updateSubmission(submissionId, 0, 0, 0, "SE", "Internal error occured."); + + Map mapMessage = new HashMap<>(); + mapMessage.put("event", "ErrorOccurred"); + mapMessage.put("submissionId", submissionId); + + messageSender.sendMessage(mapMessage); + } + + /** + * 当编译阶段结束时通知用户. + * + * @param submissionId - 评测记录的唯一标识符 + * @param result - 编译结果 + */ + public void onCompileFinished(long submissionId, Map result) { + boolean isSuccessful = (Boolean) result.get("isSuccessful"); + String log = log = getJudgeLog(result); + + if (!isSuccessful) { + updateSubmission(submissionId, 0, 0, 0, "CE", log); + } + Map mapMessage = new HashMap<>(); + mapMessage.put("event", "CompileFinished"); + mapMessage.put("submissionId", submissionId); + mapMessage.put("isSuccessful", isSuccessful); + mapMessage.put("log", log); + + messageSender.sendMessage(mapMessage); + } + + /** + * 实时返回评测结果. + * + * @param submissionId - 提交记录的编号 + * @param checkpointId - 测试点的编号 + * @param runtimeResult - 某个测试点的程序运行结果 + */ + public void onOneTestPointFinished( + long submissionId, int checkpointId, Map runtimeResult) { + String runtimeResultSlug = getRuntimeResultSlug(runtimeResult); + String runtimeResultName = getRuntimeResultName(runtimeResultSlug); + int usedTime = getUsedTime(runtimeResult); + int usedMemory = getUsedMemory(runtimeResult); + int score = getScore(runtimeResult); + + Map mapMessage = new HashMap<>(); + mapMessage.put("event", "TestPointFinished"); + mapMessage.put("submissionId", submissionId); + mapMessage.put("checkpointId", checkpointId); + mapMessage.put("runtimeResult", runtimeResultName); + mapMessage.put("usedTime", usedTime); + mapMessage.put("usedMemory", usedMemory); + mapMessage.put("score", score); + + messageSender.sendMessage(mapMessage); + } + + /** + * 持久化程序评测结果 + * + * @param submissionId - 提交记录的编号 + * @param runtimeResults - 对各个测试点的评测结果集 + */ + public void onAllTestPointsFinished(long submissionId, List> runtimeResults) { + int totalTime = 0; + int maxMemory = 0; + int totalScore = 0; + String runtimeResultSlug = "AC"; + String log = "System Error."; + + for (Map runtimeResult : runtimeResults) { + String currentRuntimeResultSlug = getRuntimeResultSlug(runtimeResult); + int usedTime = getUsedTime(runtimeResult); + int usedMemory = getUsedMemory(runtimeResult); + int score = getScore(runtimeResult); + + totalTime += usedTime; + if (usedMemory > maxMemory) { + maxMemory = usedMemory; + } + if ("AC".equals(currentRuntimeResultSlug)) { + totalScore += score; + } + if (!"AC".equals(currentRuntimeResultSlug)) { + runtimeResultSlug = currentRuntimeResultSlug; + } + } + log = getJudgeLog(runtimeResults, runtimeResultSlug, totalTime, maxMemory, totalScore); + updateSubmission(submissionId, totalTime, maxMemory, totalScore, runtimeResultSlug, log); + + Map mapMessage = new HashMap<>(); + mapMessage.put("event", "AllTestPointsFinished"); + mapMessage.put("submissionId", submissionId); + mapMessage.put("runtimeResult", getRuntimeResultName(runtimeResultSlug)); + mapMessage.put("totalTime", totalTime); + mapMessage.put("maxMemory", maxMemory); + mapMessage.put("totalScore", totalScore); + + messageSender.sendMessage(mapMessage); + } + + /** + * 从评测结果集中获取程序评测结果的唯一英文缩写. + * + * @param runtimeResult - 程序评测结果 + * @return 程序评测结果的唯一英文缩写 + */ + private String getRuntimeResultSlug(Map runtimeResult) { + Object runtimeResultObject = runtimeResult.get("runtimeResult"); + + if (runtimeResultObject == null) { + return "SE"; + } + return (String) runtimeResultObject; + } + + /** + * 获取评测结果的全称. + * + * @param runtimeResultSlug - 评测结果的唯一英文缩写 + * @return 评测结果的全称 + */ + private String getRuntimeResultName(String runtimeResultSlug) { + JudgeResult judgeResult = judgeResultMapper.getJudgeResultUsingSlug(runtimeResultSlug); + + if (judgeResult == null) { + return "System Error"; + } + return judgeResult.getJudgeResultName(); + } + + /** + * 从评测结果集中获取程序运行时间(ms). + * + * @param runtimeResult - 程序评测结果 + * @return 程序运行时间(ms) + */ + private int getUsedTime(Map runtimeResult) { + Object usedTimeObject = runtimeResult.get("usedTime"); + + if (usedTimeObject == null) { + return 0; + } + return (Integer) usedTimeObject; + } + + /** + * 从评测结果集中获取内存使用量(KB). + * + * @param runtimeResult - 程序评测结果 + * @return 内存使用量(KB) + */ + private int getUsedMemory(Map runtimeResult) { + Object usedMemoryObject = runtimeResult.get("usedMemory"); + + if (usedMemoryObject == null) { + return 0; + } + return (Integer) usedMemoryObject; + } + + /** + * 从评测结果集中获取测试点对应的分值 + * + * @param runtimeResult - 程序评测结果 + * @return 测试点对应的分值 + */ + private int getScore(Map runtimeResult) { + Object scoreObject = runtimeResult.get("score"); + + if (scoreObject == null) { + return 0; + } + return (Integer) scoreObject; + } + + /** + * 格式化编译时日志. + * + * @param result - 包含编译状态的Map对象 + * @return 格式化后的日志 + */ + private String getJudgeLog(Map result) { + boolean isSuccessful = (Boolean) result.get("isSuccessful"); + String compileLog = (String) result.get("log"); + + StringBuilder formatedLogBuilder = new StringBuilder(); + formatedLogBuilder.append( + String.format("Compile %s.\n\n", new Object[] {isSuccessful ? "Successful" : "Error"})); + if (!isSuccessful) { + formatedLogBuilder.append(compileLog.replace("\n", "\n\n")); + formatedLogBuilder.append("\nCompile Error, Time = 0 ms, Memory = 0 KB, Score = 0.\n"); + } + return formatedLogBuilder.toString(); + } + + /** + * 格式化运行时日志. + * + * @param runtimeResults - 对各个测试点的评测结果集 + * @param runtimeResultSlug + * @param totalTime + * @param maxMemory + * @param totalScore + * @return + */ + private String getJudgeLog( + List> runtimeResults, + String runtimeResultSlug, + int totalTime, + int maxMemory, + int totalScore) { + int checkpointId = -1; + String runtimeResultName = getRuntimeResultName(runtimeResultSlug); + + StringBuilder formatedLogBuilder = new StringBuilder(); + formatedLogBuilder.append("Compile Successfully.\n\n"); + for (Map runtimeResult : runtimeResults) { + String currentRuntimeResultSlug = getRuntimeResultSlug(runtimeResult); + String currentRuntimeResultName = getRuntimeResultName(currentRuntimeResultSlug); + int usedTime = getUsedTime(runtimeResult); + int usedMemory = getUsedMemory(runtimeResult); + int score = getScore(runtimeResult); + + if (!"AC".equals(currentRuntimeResultSlug)) { + score = 0; + } + formatedLogBuilder.append( + String.format( + "- Test Point #%d: %s, Time = %d ms, Memory = %d KB, Score = %d\n", + new Object[] { + ++checkpointId, currentRuntimeResultName, usedTime, usedMemory, score + })); + } + formatedLogBuilder.append( + String.format( + "\n%s, Time = %d ms, Memory = %d KB, Score = %d\n", + new Object[] {runtimeResultName, totalTime, maxMemory, totalScore})); + return formatedLogBuilder.toString(); + } + + /** + * 更新提交记录信息. + * + * @param submissionId - 提交记录的唯一标识符 + * @param usedTime - 提交运行使用时间(所有时间之和) + * @param usedMemory - 提交运行使用内存(最大内存占用) + * @param score - 运行得分 + * @param judgeResult - 运行结果(JudgeResultSlug) + * @param log - 运行日志记录 + */ + private void updateSubmission( + long submissionId, int usedTime, int usedMemory, int score, String judgeResult, String log) { + Submission submission = submissionMapper.getSubmission(submissionId); + submission.setExecuteTime(new Date()); + submission.setUsedTime(usedTime); + submission.setUsedMemory(usedMemory); + submission.setJudgeScore(score); + submission.setJudgeResultSlug(judgeResult); + submission.setJudgeLog(log); + + submissionMapper.updateSubmission(submission); + } + + /** 自动注入的Dispatcher对象. 用于完成评测作业的任务调度. */ + @Autowired private Dispatcher judgerDispatcher; + + /** 自动注入的MessageSender对象. 用于向消息队列发送消息. */ + @Autowired private MessageSender messageSender; + + /** 自动注入的SubmissionMapper对象. 用于查询/更新提交记录的相关信息. */ + @Autowired private SubmissionMapper submissionMapper; + + /** 自动注入的JudgeResultMapper对象. 用于全部评测结果的信息. */ + @Autowired private JudgeResultMapper judgeResultMapper; + + /** 日志记录器. */ + private static final Logger LOGGER = LogManager.getLogger(ApplicationDispatcher.class); } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/application/ApplicationHeartbeat.java b/judger/src/main/java/org/verwandlung/voj/judger/application/ApplicationHeartbeat.java index 98b4efa8..400a14ba 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/application/ApplicationHeartbeat.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/application/ApplicationHeartbeat.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -55,93 +55,75 @@ import org.verwandlung.voj.judger.util.DigestUtils; /** - * 应用程序心跳. - * 用于向Web模块发送Keep-Alive信息. - * + * 应用程序心跳. 用于向Web模块发送Keep-Alive信息. + * * @author Haozhe Xie */ @Component public class ApplicationHeartbeat implements Runnable { - /* (non-Javadoc) - * @see java.lang.Runnable#run() - */ - public void run() { - if ( !isIdentityValid() ) { - LOGGER.error("Unauthorized: Please check your username and password."); - System.exit(-1); - } - Calendar calendar = Calendar.getInstance(); - long currentTime = calendar.getTimeInMillis(); - - Map mapMessage = new HashMap<>(); - mapMessage.put("event", "KeepAlive"); - mapMessage.put("username", judgerUsername); - mapMessage.put("description", getDescription()); - mapMessage.put("heartbeatTime", currentTime); - messageSender.sendMessage(mapMessage); - LOGGER.info("Heartbeat sent to the web server."); - } - - /** - * 检查评测机的身份信息是否有效. - * @return 评测机的身份信息是否有效 - */ - private boolean isIdentityValid() { - User user = userMapper.getUserUsingUsername(judgerUsername); - - if ( user != null && "judgers".equals(user.getUserGroup().getUserGroupSlug()) && - user.getPassword().equals(DigestUtils.md5Hex(judgerPassword))) { - return true; - } - return false; - } - - /** - * 获取评测机的描述信息. - * TODO 使用JNI获取计算机的硬件信息 - * @return 评测机的描述信息 - */ - private String getDescription() { - return judgerDescription; - } - - /** - * 评测机身份信息. - * 评测机的用户名. - */ - @Value("${judger.username}") - private String judgerUsername; - - /** - * 评测机身份信息. - * 评测机的密码. - */ - @Value("${judger.password}") - private String judgerPassword; - - /** - * 评测机身份信息. - * 评测机的密码. - */ - @Value("${judger.description}") - private String judgerDescription; - - /** - * 自动注入的MessageSender对象. - * 用于向消息队列发送消息. - */ - @Autowired - private MessageSender messageSender; - - /** - * 自动注入的UserMapper对象. - * 用于验证评测机的身份信息. - */ - @Autowired - private UserMapper userMapper; - - /** - * 日志记录器. - */ - private static final Logger LOGGER = LogManager.getLogger(ApplicationHeartbeat.class); + /* (non-Javadoc) + * @see java.lang.Runnable#run() + */ + public void run() { + if (!isIdentityValid()) { + LOGGER.error("Unauthorized: Please check your username and password."); + System.exit(-1); + } + Calendar calendar = Calendar.getInstance(); + long currentTime = calendar.getTimeInMillis(); + + Map mapMessage = new HashMap<>(); + mapMessage.put("event", "KeepAlive"); + mapMessage.put("username", judgerUsername); + mapMessage.put("description", getDescription()); + mapMessage.put("heartbeatTime", currentTime); + messageSender.sendMessage(mapMessage); + LOGGER.info("Heartbeat sent to the web server."); + } + + /** + * 检查评测机的身份信息是否有效. + * + * @return 评测机的身份信息是否有效 + */ + private boolean isIdentityValid() { + User user = userMapper.getUserUsingUsername(judgerUsername); + + if (user != null + && "judgers".equals(user.getUserGroup().getUserGroupSlug()) + && user.getPassword().equals(DigestUtils.md5Hex(judgerPassword))) { + return true; + } + return false; + } + + /** + * 获取评测机的描述信息. TODO 使用JNI获取计算机的硬件信息 + * + * @return 评测机的描述信息 + */ + private String getDescription() { + return judgerDescription; + } + + /** 评测机身份信息. 评测机的用户名. */ + @Value("${judger.username}") + private String judgerUsername; + + /** 评测机身份信息. 评测机的密码. */ + @Value("${judger.password}") + private String judgerPassword; + + /** 评测机身份信息. 评测机的密码. */ + @Value("${judger.description}") + private String judgerDescription; + + /** 自动注入的MessageSender对象. 用于向消息队列发送消息. */ + @Autowired private MessageSender messageSender; + + /** 自动注入的UserMapper对象. 用于验证评测机的身份信息. */ + @Autowired private UserMapper userMapper; + + /** 日志记录器. */ + private static final Logger LOGGER = LogManager.getLogger(ApplicationHeartbeat.class); } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/core/Comparator.java b/judger/src/main/java/org/verwandlung/voj/judger/core/Comparator.java index 1c223eeb..55f554b7 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/core/Comparator.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/core/Comparator.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -50,122 +50,124 @@ /** * 用于比对用户输出结果和标准结果. - * + * * @author Haozhe Xie */ @Component public class Comparator { - /** - * 获取用户输出和标准输出的比对结果. - * @param standardOutputFilePath - 标准输出文件路径 - * @param outputFilePath - 用户输出文件路径 - * @return 用户输出和标准输出是否相同 - */ - public boolean isOutputTheSame(String standardOutputFilePath, - String outputFilePath) throws IOException { - File stdFile = new File(standardOutputFilePath); - File file = new File(outputFilePath); + /** + * 获取用户输出和标准输出的比对结果. + * + * @param standardOutputFilePath - 标准输出文件路径 + * @param outputFilePath - 用户输出文件路径 + * @return 用户输出和标准输出是否相同 + */ + public boolean isOutputTheSame(String standardOutputFilePath, String outputFilePath) + throws IOException { + File stdFile = new File(standardOutputFilePath); + File file = new File(outputFilePath); + + LineIterator stdFileItr = FileUtils.lineIterator(stdFile, "UTF-8"); + LineIterator fileItr = FileUtils.lineIterator(file, "UTF-8"); + boolean isFileOutputTheSame = isFileOutputTheSame(stdFileItr, fileItr); + + LineIterator.closeQuietly(stdFileItr); + LineIterator.closeQuietly(fileItr); + return isFileOutputTheSame; + } + + /** + * 比对标准输出和用户输出是否相同. + * + * @param stdFileItr - 标准输出文件的迭代器 + * @param fileItr - 用户输出文件的迭代器 + * @return 标准输出和用户输出是否相同 + */ + private boolean isFileOutputTheSame(LineIterator stdFileItr, LineIterator fileItr) { + try { + while (stdFileItr.hasNext() && fileItr.hasNext()) { + String stdLine = stdFileItr.nextLine(); + String line = fileItr.nextLine(); + + if (!isLineOutputTheSame(stdLine, line)) { + return false; + } + } + while (stdFileItr.hasNext()) { + String line = stdFileItr.nextLine(); + if (!isLineEmpty(line, 0)) { + return false; + } + } + while (fileItr.hasNext()) { + String line = fileItr.nextLine(); + if (!isLineEmpty(line, 0)) { + return false; + } + } + } catch (OutOfMemoryError ex) { + LOGGER.catching(ex); + return false; + } + return true; + } + + /** + * 比对某行的标准输出和用户输出(忽略行尾空格). + * + * @param stdLine - 标准输出中的某一行 + * @param line - 用户输出中的某一行 + * @return 某行的标准输出和用户输出是否相同 + */ + private boolean isLineOutputTheSame(String stdLine, String line) { + int i = 0, j = 0; + for (; i < stdLine.length() && j < line.length(); ++i, ++j) { + if (stdLine.charAt(i) != line.charAt(j)) { + if (stdLine.charAt(i) == '\n') { + if (!isLineEmpty(line, j)) { + return false; + } + return true; + } else if (line.charAt(j) == '\n') { + if (!isLineEmpty(stdLine, i)) { + return false; + } + return true; + } + return false; + } + } + while (i < stdLine.length()) { + if (!isLineEmpty(stdLine, i)) { + return false; + } + ++i; + } + while (j < line.length()) { + if (!isLineEmpty(line, j)) { + return false; + } + ++j; + } + return true; + } + + /** + * 忽略文件结尾的空行与空格. + * + * @param line - 某行文件内容 + * @param startIndex - 开始检查位置的索引 + * @return 该行内容中是否只包含空格和换行符 + */ + private boolean isLineEmpty(String line, int startIndex) { + for (int i = startIndex; i < line.length(); ++i) { + if (!(line.charAt(i) == ' ' || line.charAt(i) == '\n')) { + return false; + } + } + return true; + } - LineIterator stdFileItr = FileUtils.lineIterator(stdFile, "UTF-8"); - LineIterator fileItr = FileUtils.lineIterator(file, "UTF-8"); - boolean isFileOutputTheSame = isFileOutputTheSame(stdFileItr, fileItr); - - LineIterator.closeQuietly(stdFileItr); - LineIterator.closeQuietly(fileItr); - return isFileOutputTheSame; - } - - /** - * 比对标准输出和用户输出是否相同. - * @param stdFileItr - 标准输出文件的迭代器 - * @param fileItr - 用户输出文件的迭代器 - * @return 标准输出和用户输出是否相同 - */ - private boolean isFileOutputTheSame(LineIterator stdFileItr, LineIterator fileItr) { - try { - while ( stdFileItr.hasNext() && fileItr.hasNext() ) { - String stdLine = stdFileItr.nextLine(); - String line = fileItr.nextLine(); - - if ( !isLineOutputTheSame(stdLine, line) ) { - return false; - } - } - while ( stdFileItr.hasNext() ) { - String line = stdFileItr.nextLine(); - if ( !isLineEmpty(line, 0) ) { - return false; - } - } - while ( fileItr.hasNext() ) { - String line = fileItr.nextLine(); - if ( !isLineEmpty(line, 0) ) { - return false; - } - } - } catch ( OutOfMemoryError ex ) { - LOGGER.catching(ex); - return false; - } - return true; - } - - /** - * 比对某行的标准输出和用户输出(忽略行尾空格). - * @param stdLine - 标准输出中的某一行 - * @param line - 用户输出中的某一行 - * @return 某行的标准输出和用户输出是否相同 - */ - private boolean isLineOutputTheSame(String stdLine, String line) { - int i = 0, j = 0; - for ( ; i < stdLine.length() && j < line.length(); ++ i, ++ j ) { - if ( stdLine.charAt(i) != line.charAt(j) ) { - if ( stdLine.charAt(i) == '\n' ) { - if ( !isLineEmpty(line, j) ) { - return false; - } - return true; - } else if ( line.charAt(j) == '\n' ) { - if ( !isLineEmpty(stdLine, i) ) { - return false; - } - return true; - } - return false; - } - } - while ( i < stdLine.length() ) { - if ( !isLineEmpty(stdLine, i) ) { - return false; - } - ++ i; - } - while ( j < line.length() ) { - if ( !isLineEmpty(line, j) ) { - return false; - } - ++ j; - } - return true; - } - - /** - * 忽略文件结尾的空行与空格. - * @param line - 某行文件内容 - * @param startIndex - 开始检查位置的索引 - * @return 该行内容中是否只包含空格和换行符 - */ - private boolean isLineEmpty(String line, int startIndex) { - for ( int i = startIndex; i < line.length(); ++ i ) { - if ( !(line.charAt(i) == ' ' || line.charAt(i) == '\n') ) { - return false; - } - } - return true; - } - - /** - * 日志记录器. - */ - private static final Logger LOGGER = LogManager.getLogger(Comparator.class); + /** 日志记录器. */ + private static final Logger LOGGER = LogManager.getLogger(Comparator.class); } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/core/Compiler.java b/judger/src/main/java/org/verwandlung/voj/judger/core/Compiler.java index 451e43f0..c4982235 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/core/Compiler.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/core/Compiler.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -53,107 +53,108 @@ /** * 程序编译器, 用于编译用户提交的代码. - * + * * @author Haozhe Xie */ @Component public class Compiler { - /** - * 获取编译输出结果. - * @param submission - 提交记录对象 - * @param workDirectory - 编译输出目录 - * @param baseFileName - 编译输出文件名 - * @return 包含编译输出结果的Map对象 - */ - public Map getCompileResult(Submission submission, - String workDirectory, String baseFileName) { - String commandLine = getCompileCommandLine(submission, workDirectory, baseFileName); - String compileLogPath = getCompileLogPath(workDirectory, baseFileName); + /** + * 获取编译输出结果. + * + * @param submission - 提交记录对象 + * @param workDirectory - 编译输出目录 + * @param baseFileName - 编译输出文件名 + * @return 包含编译输出结果的Map对象 + */ + public Map getCompileResult( + Submission submission, String workDirectory, String baseFileName) { + String commandLine = getCompileCommandLine(submission, workDirectory, baseFileName); + String compileLogPath = getCompileLogPath(workDirectory, baseFileName); + + return getCompileResult(commandLine, compileLogPath); + } + + /** + * 获取编译命令. + * + * @param submission - 提交记录对象 + * @param workDirectory - 编译输出目录 + * @param baseFileName - 编译输出文件名 + * @return 编译命令 + */ + private String getCompileCommandLine( + Submission submission, String workDirectory, String baseFileName) { + String filePathWithoutExtension = + String.format("%s/%s", new Object[] {workDirectory, baseFileName}); + String compileCommand = + submission + .getLanguage() + .getCompileCommand() + .replaceAll("\\{filename\\}", filePathWithoutExtension); + return compileCommand; + } + + /** + * 获取编译日志输出的文件路径. + * + * @param workDirectory - 编译输出目录 + * @param baseFileName - 编译输出文件名 + * @return 编译日志输出的文件路径 + */ + private String getCompileLogPath(String workDirectory, String baseFileName) { + return String.format("%s/%s-compile.log", new Object[] {workDirectory, baseFileName}); + } + + /** + * 获取编译输出结果. + * + * @param commandLine - 编译命令 + * @param compileLogPath - 编译日志输出路径 + * @return 包含编译输出结果的Map对象 + */ + private Map getCompileResult(String commandLine, String compileLogPath) { + String inputFilePath = null; + int timeLimit = 5000; + int memoryLimit = 0; + + LOGGER.info("Start compiling with command: " + commandLine); + Map runningResult = + compilerRunner.getRuntimeResult( + commandLine, inputFilePath, compileLogPath, timeLimit, memoryLimit); + Map result = new HashMap<>(3, 1); + + boolean isSuccessful = false; + if (runningResult != null) { + int exitCode = (Integer) runningResult.get("exitCode"); + isSuccessful = exitCode == 0; + } + result.put("isSuccessful", isSuccessful); + result.put("log", getCompileOutput(compileLogPath)); + return result; + } + + /** + * 获取编译日志内容. + * + * @param compileLogPath - 编译日志路径 + * @return 编译日志内容 + */ + private String getCompileOutput(String compileLogPath) { + FileInputStream inputStream = null; + String compileLog = ""; + try { + inputStream = new FileInputStream(compileLogPath); + compileLog = IOUtils.toString(inputStream); + inputStream.close(); + } catch (Exception ex) { + // Do nothing + } + return compileLog; + } + + /** 自动注入的Runner对象. 用于执行编译命令. */ + @Autowired private Runner compilerRunner; - return getCompileResult(commandLine, compileLogPath); - } - - /** - * 获取编译命令. - * @param submission - 提交记录对象 - * @param workDirectory - 编译输出目录 - * @param baseFileName - 编译输出文件名 - * @return 编译命令 - */ - private String getCompileCommandLine(Submission submission, - String workDirectory, String baseFileName) { - String filePathWithoutExtension = String.format("%s/%s", - new Object[] {workDirectory, baseFileName}); - String compileCommand = submission.getLanguage() - .getCompileCommand() - .replaceAll("\\{filename\\}", filePathWithoutExtension); - return compileCommand; - } - - /** - * 获取编译日志输出的文件路径. - * @param workDirectory - 编译输出目录 - * @param baseFileName - 编译输出文件名 - * @return 编译日志输出的文件路径 - */ - private String getCompileLogPath(String workDirectory, String baseFileName) { - return String.format("%s/%s-compile.log", - new Object[] {workDirectory, baseFileName}); - } - - /** - * 获取编译输出结果. - * @param commandLine - 编译命令 - * @param compileLogPath - 编译日志输出路径 - * @return 包含编译输出结果的Map对象 - */ - private Map getCompileResult(String commandLine, String compileLogPath) { - String inputFilePath = null; - int timeLimit = 5000; - int memoryLimit = 0; - - LOGGER.info("Start compiling with command: " + commandLine); - Map runningResult = compilerRunner.getRuntimeResult( - commandLine, inputFilePath, compileLogPath, timeLimit, memoryLimit); - Map result = new HashMap<>(3, 1); - - boolean isSuccessful = false; - if ( runningResult != null ) { - int exitCode = (Integer)runningResult.get("exitCode"); - isSuccessful = exitCode == 0; - } - result.put("isSuccessful", isSuccessful); - result.put("log", getCompileOutput(compileLogPath)); - return result; - } - - /** - * 获取编译日志内容. - * @param compileLogPath - 编译日志路径 - * @return 编译日志内容 - */ - private String getCompileOutput(String compileLogPath) { - FileInputStream inputStream = null; - String compileLog = ""; - try { - inputStream = new FileInputStream(compileLogPath); - compileLog = IOUtils.toString(inputStream); - inputStream.close(); - } catch (Exception ex) { - // Do nothing - } - return compileLog; - } - - /** - * 自动注入的Runner对象. - * 用于执行编译命令. - */ - @Autowired - private Runner compilerRunner; - - /** - * 日志记录器. - */ - private static final Logger LOGGER = LogManager.getLogger(Compiler.class); + /** 日志记录器. */ + private static final Logger LOGGER = LogManager.getLogger(Compiler.class); } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/core/Dispatcher.java b/judger/src/main/java/org/verwandlung/voj/judger/core/Dispatcher.java index 9926679d..9feb7499 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/core/Dispatcher.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/core/Dispatcher.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -62,248 +62,217 @@ import org.verwandlung.voj.judger.util.DigestUtils; /** - * 评测机调度器. - * 用于完成评测机的评测流程. - * 每个阶段结束后推送消息至消息队列; 评测结束后写入数据库. + * 评测机调度器. 用于完成评测机的评测流程. 每个阶段结束后推送消息至消息队列; 评测结束后写入数据库. * * @author Haozhe Xie */ @Component public class Dispatcher { - /** - * 创建新的评测任务. - * 每次只运行一个评测任务. - * @param submissionId - 提交记录的唯一标识符 - * @throws IllgealSubmissionException - * @throws InterruptedException - */ - public void createNewTask(long submissionId) throws IllgealSubmissionException, InterruptedException { - synchronized(this) { - String baseDirectory = String.format("%s/voj-%s", new Object[] {workBaseDirectory, submissionId}); - String baseFileName = DigestUtils.getRandomString(12, DigestUtils.Mode.ALPHA); - - // 解决由于未知原因无法获取到数据记录的问题 - int tryTimes = 0; - Submission submission = null; - do { - Thread.sleep(1000); - submission = submissionMapper.getSubmission(submissionId); - } while ( submission == null && ++ tryTimes <= 3 ); - - if ( submission == null ) { - throw new IllgealSubmissionException( - String.format("Illegal submission #%s", - new Object[] { submissionId })); - } - preprocess(submission, baseDirectory, baseFileName); - if ( compile(submission, baseDirectory, baseFileName) ) { - runProgram(submission, baseDirectory, baseFileName); - } - cleanUp(baseDirectory); - } - } + /** + * 创建新的评测任务. 每次只运行一个评测任务. + * + * @param submissionId - 提交记录的唯一标识符 + * @throws IllgealSubmissionException + * @throws InterruptedException + */ + public void createNewTask(long submissionId) + throws IllgealSubmissionException, InterruptedException { + synchronized (this) { + String baseDirectory = + String.format("%s/voj-%s", new Object[] {workBaseDirectory, submissionId}); + String baseFileName = DigestUtils.getRandomString(12, DigestUtils.Mode.ALPHA); - /** - * 完成评测前的预处理工作. - * 说明: 随机文件名用于防止应用程序自身递归调用. - * - * @param submission - 评测记录对象 - * @param workDirectory - 用于产生编译输出的目录 - * @param baseFileName - 随机文件名(不包含后缀) - */ - private void preprocess(Submission submission, - String workDirectory, String baseFileName) { - try { - long problemId = submission.getProblem().getProblemId(); - preprocessor.createTestCode(submission, workDirectory, baseFileName); - preprocessor.fetchTestPoints(problemId); - } catch (Exception ex) { - LOGGER.catching(ex); + // 解决由于未知原因无法获取到数据记录的问题 + int tryTimes = 0; + Submission submission = null; + do { + Thread.sleep(1000); + submission = submissionMapper.getSubmission(submissionId); + } while (submission == null && ++tryTimes <= 3); - long submissionId = submission.getSubmissionId(); - applicationDispatcher.onErrorOccurred(submissionId); - } - } + if (submission == null) { + throw new IllgealSubmissionException( + String.format("Illegal submission #%s", new Object[] {submissionId})); + } + preprocess(submission, baseDirectory, baseFileName); + if (compile(submission, baseDirectory, baseFileName)) { + runProgram(submission, baseDirectory, baseFileName); + } + cleanUp(baseDirectory); + } + } - /** - * 创建编译任务. - * 说明: 随机文件名用于防止应用程序自身递归调用. - * - * @param submission - 评测记录对象 - * @param workDirectory - 用于产生编译输出的目录 - * @param baseFileName - 随机文件名(不包含后缀) - */ - private boolean compile(Submission submission, - String workDirectory, String baseFileName) { - long submissionId = submission.getSubmissionId(); - Map result = - compiler.getCompileResult(submission, workDirectory, baseFileName); + /** + * 完成评测前的预处理工作. 说明: 随机文件名用于防止应用程序自身递归调用. + * + * @param submission - 评测记录对象 + * @param workDirectory - 用于产生编译输出的目录 + * @param baseFileName - 随机文件名(不包含后缀) + */ + private void preprocess(Submission submission, String workDirectory, String baseFileName) { + try { + long problemId = submission.getProblem().getProblemId(); + preprocessor.createTestCode(submission, workDirectory, baseFileName); + preprocessor.fetchTestPoints(problemId); + } catch (Exception ex) { + LOGGER.catching(ex); - applicationDispatcher.onCompileFinished(submissionId, result); - return (Boolean)result.get("isSuccessful"); - } + long submissionId = submission.getSubmissionId(); + applicationDispatcher.onErrorOccurred(submissionId); + } + } - /** - * 执行程序. - * @param submission - 评测记录对象 - * @param workDirectory - 编译生成结果的目录以及程序输出的目录 - * @param baseFileName - 待执行的应用程序文件名(不包含文件后缀) - */ - private void runProgram(Submission submission, - String workDirectory, String baseFileName) { - List> runtimeResults = new ArrayList>(); - long submissionId = submission.getSubmissionId(); - long problemId = submission.getProblem().getProblemId(); + /** + * 创建编译任务. 说明: 随机文件名用于防止应用程序自身递归调用. + * + * @param submission - 评测记录对象 + * @param workDirectory - 用于产生编译输出的目录 + * @param baseFileName - 随机文件名(不包含后缀) + */ + private boolean compile(Submission submission, String workDirectory, String baseFileName) { + long submissionId = submission.getSubmissionId(); + Map result = compiler.getCompileResult(submission, workDirectory, baseFileName); - List checkpoints = checkpointMapper.getCheckpointsUsingProblemId(problemId); - for ( Checkpoint checkpoint : checkpoints ) { - int checkpointId = checkpoint.getCheckpointId(); - int checkpointScore = checkpoint.getScore(); - String inputFilePath = String.format("%s/%s/input#%s.txt", - new Object[] { checkpointDirectory, problemId, checkpointId }); - String stdOutputFilePath = String.format("%s/%s/output#%s.txt", - new Object[] { checkpointDirectory, problemId, checkpointId }); - String outputFilePath = getOutputFilePath(workDirectory, checkpointId); + applicationDispatcher.onCompileFinished(submissionId, result); + return (Boolean) result.get("isSuccessful"); + } - Map runtimeResult = getRuntimeResult( - runner.getRuntimeResult(submission, workDirectory, baseFileName, inputFilePath, outputFilePath), - stdOutputFilePath, outputFilePath); - runtimeResult.put("score", checkpointScore); - runtimeResults.add(runtimeResult); - applicationDispatcher.onOneTestPointFinished(submissionId, checkpointId, runtimeResult); - } - applicationDispatcher.onAllTestPointsFinished(submissionId, runtimeResults); - } + /** + * 执行程序. + * + * @param submission - 评测记录对象 + * @param workDirectory - 编译生成结果的目录以及程序输出的目录 + * @param baseFileName - 待执行的应用程序文件名(不包含文件后缀) + */ + private void runProgram(Submission submission, String workDirectory, String baseFileName) { + List> runtimeResults = new ArrayList>(); + long submissionId = submission.getSubmissionId(); + long problemId = submission.getProblem().getProblemId(); - /** - * 获取当前测试点输出路径. - * @param workDirectory - 编译生成结果的目录以及程序输出的目录 - * @param checkpointId - 当前测试点编号 - * @return 当前测试点输出路径 - */ - private String getOutputFilePath(String workDirectory, int checkpointId) { - return String.format("%s/output#%s.txt", - new Object[] {workDirectory, checkpointId}); - } + List checkpoints = checkpointMapper.getCheckpointsUsingProblemId(problemId); + for (Checkpoint checkpoint : checkpoints) { + int checkpointId = checkpoint.getCheckpointId(); + int checkpointScore = checkpoint.getScore(); + String inputFilePath = + String.format( + "%s/%s/input#%s.txt", new Object[] {checkpointDirectory, problemId, checkpointId}); + String stdOutputFilePath = + String.format( + "%s/%s/output#%s.txt", new Object[] {checkpointDirectory, problemId, checkpointId}); + String outputFilePath = getOutputFilePath(workDirectory, checkpointId); - /** - * 获取程序运行结果(及答案比对结果). - * @param result - 包含程序运行结果的Map对象 - * @param standardOutputFilePath - 标准输出文件路径 - * @param outputFilePath - 用户输出文件路径 - * @return 包含程序运行结果的Map对象 - */ - private Map getRuntimeResult(Map result, - String standardOutputFilePath, String outputFilePath) { - String runtimeResultSlug = (String)result.get("runtimeResult"); - int usedTime = (Integer)result.get("usedTime"); - int usedMemory = (Integer)result.get("usedMemory"); + Map runtimeResult = + getRuntimeResult( + runner.getRuntimeResult( + submission, workDirectory, baseFileName, inputFilePath, outputFilePath), + stdOutputFilePath, + outputFilePath); + runtimeResult.put("score", checkpointScore); + runtimeResults.add(runtimeResult); + applicationDispatcher.onOneTestPointFinished(submissionId, checkpointId, runtimeResult); + } + applicationDispatcher.onAllTestPointsFinished(submissionId, runtimeResults); + } - if ( runtimeResultSlug.equals("AC") && - !isOutputTheSame(standardOutputFilePath, outputFilePath) ) { - runtimeResultSlug = "WA"; - result.put("runtimeResult", runtimeResultSlug); - } - LOGGER.info(String.format("RuntimeResult: [%s, Time: %d ms, Memory: %d KB]", - new Object[] { runtimeResultSlug, usedTime, usedMemory })); + /** + * 获取当前测试点输出路径. + * + * @param workDirectory - 编译生成结果的目录以及程序输出的目录 + * @param checkpointId - 当前测试点编号 + * @return 当前测试点输出路径 + */ + private String getOutputFilePath(String workDirectory, int checkpointId) { + return String.format("%s/output#%s.txt", new Object[] {workDirectory, checkpointId}); + } - return result; - } + /** + * 获取程序运行结果(及答案比对结果). + * + * @param result - 包含程序运行结果的Map对象 + * @param standardOutputFilePath - 标准输出文件路径 + * @param outputFilePath - 用户输出文件路径 + * @return 包含程序运行结果的Map对象 + */ + private Map getRuntimeResult( + Map result, String standardOutputFilePath, String outputFilePath) { + String runtimeResultSlug = (String) result.get("runtimeResult"); + int usedTime = (Integer) result.get("usedTime"); + int usedMemory = (Integer) result.get("usedMemory"); - /** - * 获取用户输出和标准输出的比对结果. - * @param standardOutputFilePath - 标准输出文件路径 - * @param outputFilePath - 用户输出文件路径 - * @return 用户输出和标准输出是否相同 - */ - private boolean isOutputTheSame(String standardOutputFilePath, String outputFilePath) { - try { - return comparator.isOutputTheSame(standardOutputFilePath, outputFilePath); - } catch (IOException ex) { - LOGGER.catching(ex); - } - return false; - } + if (runtimeResultSlug.equals("AC") + && !isOutputTheSame(standardOutputFilePath, outputFilePath)) { + runtimeResultSlug = "WA"; + result.put("runtimeResult", runtimeResultSlug); + } + LOGGER.info( + String.format( + "RuntimeResult: [%s, Time: %d ms, Memory: %d KB]", + new Object[] {runtimeResultSlug, usedTime, usedMemory})); - /** - * 评测完成后, 清理所生成的文件. - * @param baseDirectory - 用于产生输出结果目录 - */ - private void cleanUp(String baseDirectory) { - File baseDirFile = new File(baseDirectory); - if ( baseDirFile.exists() ) { - try { - FileUtils.deleteDirectory(baseDirFile); - } catch (IOException ex) { - LOGGER.catching(ex); - } - } - } + return result; + } - /** - * 自动注入的ApplicationDispatcher对象. - * 完成每个阶段的任务后推送消息至消息队列. - */ - @Autowired - private ApplicationDispatcher applicationDispatcher; + /** + * 获取用户输出和标准输出的比对结果. + * + * @param standardOutputFilePath - 标准输出文件路径 + * @param outputFilePath - 用户输出文件路径 + * @return 用户输出和标准输出是否相同 + */ + private boolean isOutputTheSame(String standardOutputFilePath, String outputFilePath) { + try { + return comparator.isOutputTheSame(standardOutputFilePath, outputFilePath); + } catch (IOException ex) { + LOGGER.catching(ex); + } + return false; + } - /** - * 自动注入的Preprocessor对象. - * 完成编译前的准备工作. - */ - @Autowired - private Preprocessor preprocessor; + /** + * 评测完成后, 清理所生成的文件. + * + * @param baseDirectory - 用于产生输出结果目录 + */ + private void cleanUp(String baseDirectory) { + File baseDirFile = new File(baseDirectory); + if (baseDirFile.exists()) { + try { + FileUtils.deleteDirectory(baseDirFile); + } catch (IOException ex) { + LOGGER.catching(ex); + } + } + } - /** - * 自动注入的Compiler对象. - * 完成编译工作. - */ - @Autowired - private Compiler compiler; + /** 自动注入的ApplicationDispatcher对象. 完成每个阶段的任务后推送消息至消息队列. */ + @Autowired private ApplicationDispatcher applicationDispatcher; - /** - * 自动注入的Runner对象. - * 完成程序运行工作. - */ - @Autowired - private Runner runner; + /** 自动注入的Preprocessor对象. 完成编译前的准备工作. */ + @Autowired private Preprocessor preprocessor; - /** - * 自动注入的Matcher对象. - * 完成输出结果比对工作. - */ - @Autowired - private Comparator comparator; + /** 自动注入的Compiler对象. 完成编译工作. */ + @Autowired private Compiler compiler; - /** - * 自动注入的SubmissionMapper对象. - */ - @Autowired - private SubmissionMapper submissionMapper; + /** 自动注入的Runner对象. 完成程序运行工作. */ + @Autowired private Runner runner; - /** - * 自动注入的CheckpointMapper对象. - * 用于获取试题的测试点. - */ - @Autowired - private CheckpointMapper checkpointMapper; + /** 自动注入的Matcher对象. 完成输出结果比对工作. */ + @Autowired private Comparator comparator; - /** - * 评测机的工作目录. - * 用于存储编译结果以及程序输出结果. - */ - @Value("${judger.workDir}") - private String workBaseDirectory; + /** 自动注入的SubmissionMapper对象. */ + @Autowired private SubmissionMapper submissionMapper; - /** - * 测试点的存储目录. - * 用于存储测试点的输入输出数据. - */ - @Value("${judger.checkpointDir}") - private String checkpointDirectory; + /** 自动注入的CheckpointMapper对象. 用于获取试题的测试点. */ + @Autowired private CheckpointMapper checkpointMapper; - /** - * 日志记录器. - */ - private static final Logger LOGGER = LogManager.getLogger(Dispatcher.class); + /** 评测机的工作目录. 用于存储编译结果以及程序输出结果. */ + @Value("${judger.workDir}") + private String workBaseDirectory; + + /** 测试点的存储目录. 用于存储测试点的输入输出数据. */ + @Value("${judger.checkpointDir}") + private String checkpointDirectory; + + /** 日志记录器. */ + private static final Logger LOGGER = LogManager.getLogger(Dispatcher.class); } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/core/Preprocessor.java b/judger/src/main/java/org/verwandlung/voj/judger/core/Preprocessor.java index dc8ab611..c0db4c44 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/core/Preprocessor.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/core/Preprocessor.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -63,139 +63,136 @@ /** * 预处理器, 用于完成评测前准备工作. - * + * * @author Haozhe Xie */ @Component public class Preprocessor { - /** - * 创建测试代码至本地磁盘. - * - * @param submission - 评测记录对象 - * @param workDirectory - 用于产生编译输出的目录 - * @param baseFileName - 随机文件名(不包含后缀) - * @throws Exception - */ - public void createTestCode(Submission submission, - String workDirectory, String baseFileName) throws Exception { - File workDirFile = new File(workDirectory); - if ( !workDirFile.exists() && !workDirFile.mkdirs() ) { - throw new CreateDirectoryException("Failed to create directory: " + workDirectory); - } - setWorkDirectoryPermission(workDirFile); - - Language language = submission.getLanguage(); - String code = replaceClassName(language, submission.getCode(), baseFileName); - String codeFilePath = String.format("%s/%s.%s", - new Object[] {workDirectory, baseFileName, getCodeFileSuffix(language)}); - - FileOutputStream outputStream = new FileOutputStream(new File(codeFilePath)); - IOUtils.write(code, outputStream); - IOUtils.closeQuietly(outputStream); - } - - /** - * 获取代码文件的后缀名. - * @param language - 编程语言对象 - * @return 代码文件的后缀名 - */ - private String getCodeFileSuffix(Language language) { - String compileCommand = language.getCompileCommand(); - - Pattern pattern = Pattern.compile("\\{filename\\}\\.((?!exe| ).)+"); - Matcher matcher = pattern.matcher(compileCommand); - - if ( matcher.find() ) { - String sourceFileName = matcher.group(); - return sourceFileName.replaceAll("\\{filename\\}\\.", ""); - } - return ""; - } - - /** - * 替换部分语言中的类名(如Java), 以保证正常通过编译. - * @param language - 编程语言对象 - * @param code - 待替换的代码 - * @param newClassName - 新的类名 - */ - private String replaceClassName(Language language, String code, String newClassName) { - if ( !language.getLanguageName().equalsIgnoreCase("Java") ) { - return code; - } - return code.replaceAll("class[ \n]+Main", "class " + newClassName); - } - - /** - * 设置代码文件所在目录的读写权限. - * 在Linux下, 代码以UID=1536的用户运行, 因此需要为Others用户组分配写权限. - * @param workDirectory 用于产生编译输出的目录 - */ - private void setWorkDirectoryPermission(File workDirectory) throws IOException { - if ( !System.getProperty("os.name").contains("Windows") ) { - Set permissions = new HashSet<>(); - - permissions.add(PosixFilePermission.OWNER_READ); - permissions.add(PosixFilePermission.OWNER_WRITE); - permissions.add(PosixFilePermission.OWNER_EXECUTE); - - permissions.add(PosixFilePermission.GROUP_READ); - permissions.add(PosixFilePermission.GROUP_WRITE); - permissions.add(PosixFilePermission.GROUP_EXECUTE); - - permissions.add(PosixFilePermission.OTHERS_READ); - permissions.add(PosixFilePermission.OTHERS_WRITE); - permissions.add(PosixFilePermission.OTHERS_EXECUTE); - Files.setPosixFilePermissions(workDirectory.toPath(), permissions); - } - } - - /** - * 从数据库抓取评测数据. - * @param problemId - 试题的唯一标识符 - * @throws Exception - */ - public void fetchTestPoints(long problemId) throws Exception { - String checkpointsFilePath = String.format("%s/%s", - new Object[] {checkpointDirectory, problemId}); - File checkpointsDirFile = new File(checkpointsFilePath); - if ( !checkpointsDirFile.exists() && !checkpointsDirFile.mkdirs() ) { - throw new CreateDirectoryException("Failed to create the checkpoints directory: " + checkpointsFilePath); - } - - List checkpoints = - checkpointMapper.getCheckpointsUsingProblemId(problemId); - for ( Checkpoint checkpoint : checkpoints ) { - long checkpointId = checkpoint.getCheckpointId(); - { // Standard Input File - String filePath = String.format("%s/input#%s.txt", - new Object[] { checkpointsFilePath, checkpointId }); - FileOutputStream outputStream = new FileOutputStream(new File(filePath)); - String input = checkpoint.getInput(); - IOUtils.write(input, outputStream); - IOUtils.closeQuietly(outputStream); - } - { // Standard Output File - String filePath = String.format("%s/output#%s.txt", - new Object[] { checkpointsFilePath, checkpointId }); - FileOutputStream outputStream = new FileOutputStream(new File(filePath)); - String output = checkpoint.getOutput(); - IOUtils.write(output, outputStream); - IOUtils.closeQuietly(outputStream); - } - } - } - - /** - * 自动注入的CheckpointMapper对象. - * 用于获取试题的测试点. - */ - @Autowired - private CheckpointMapper checkpointMapper; - - /** - * 测试点的存储目录. - * 用于存储测试点的输入输出数据. - */ - @Value("${judger.checkpointDir}") - private String checkpointDirectory; + /** + * 创建测试代码至本地磁盘. + * + * @param submission - 评测记录对象 + * @param workDirectory - 用于产生编译输出的目录 + * @param baseFileName - 随机文件名(不包含后缀) + * @throws Exception + */ + public void createTestCode(Submission submission, String workDirectory, String baseFileName) + throws Exception { + File workDirFile = new File(workDirectory); + if (!workDirFile.exists() && !workDirFile.mkdirs()) { + throw new CreateDirectoryException("Failed to create directory: " + workDirectory); + } + setWorkDirectoryPermission(workDirFile); + + Language language = submission.getLanguage(); + String code = replaceClassName(language, submission.getCode(), baseFileName); + String codeFilePath = + String.format( + "%s/%s.%s", new Object[] {workDirectory, baseFileName, getCodeFileSuffix(language)}); + + FileOutputStream outputStream = new FileOutputStream(new File(codeFilePath)); + IOUtils.write(code, outputStream); + IOUtils.closeQuietly(outputStream); + } + + /** + * 获取代码文件的后缀名. + * + * @param language - 编程语言对象 + * @return 代码文件的后缀名 + */ + private String getCodeFileSuffix(Language language) { + String compileCommand = language.getCompileCommand(); + + Pattern pattern = Pattern.compile("\\{filename\\}\\.((?!exe| ).)+"); + Matcher matcher = pattern.matcher(compileCommand); + + if (matcher.find()) { + String sourceFileName = matcher.group(); + return sourceFileName.replaceAll("\\{filename\\}\\.", ""); + } + return ""; + } + + /** + * 替换部分语言中的类名(如Java), 以保证正常通过编译. + * + * @param language - 编程语言对象 + * @param code - 待替换的代码 + * @param newClassName - 新的类名 + */ + private String replaceClassName(Language language, String code, String newClassName) { + if (!language.getLanguageName().equalsIgnoreCase("Java")) { + return code; + } + return code.replaceAll("class[ \n]+Main", "class " + newClassName); + } + + /** + * 设置代码文件所在目录的读写权限. 在Linux下, 代码以UID=1536的用户运行, 因此需要为Others用户组分配写权限. + * + * @param workDirectory 用于产生编译输出的目录 + */ + private void setWorkDirectoryPermission(File workDirectory) throws IOException { + if (!System.getProperty("os.name").contains("Windows")) { + Set permissions = new HashSet<>(); + + permissions.add(PosixFilePermission.OWNER_READ); + permissions.add(PosixFilePermission.OWNER_WRITE); + permissions.add(PosixFilePermission.OWNER_EXECUTE); + + permissions.add(PosixFilePermission.GROUP_READ); + permissions.add(PosixFilePermission.GROUP_WRITE); + permissions.add(PosixFilePermission.GROUP_EXECUTE); + + permissions.add(PosixFilePermission.OTHERS_READ); + permissions.add(PosixFilePermission.OTHERS_WRITE); + permissions.add(PosixFilePermission.OTHERS_EXECUTE); + Files.setPosixFilePermissions(workDirectory.toPath(), permissions); + } + } + + /** + * 从数据库抓取评测数据. + * + * @param problemId - 试题的唯一标识符 + * @throws Exception + */ + public void fetchTestPoints(long problemId) throws Exception { + String checkpointsFilePath = + String.format("%s/%s", new Object[] {checkpointDirectory, problemId}); + File checkpointsDirFile = new File(checkpointsFilePath); + if (!checkpointsDirFile.exists() && !checkpointsDirFile.mkdirs()) { + throw new CreateDirectoryException( + "Failed to create the checkpoints directory: " + checkpointsFilePath); + } + + List checkpoints = checkpointMapper.getCheckpointsUsingProblemId(problemId); + for (Checkpoint checkpoint : checkpoints) { + long checkpointId = checkpoint.getCheckpointId(); + { // Standard Input File + String filePath = + String.format("%s/input#%s.txt", new Object[] {checkpointsFilePath, checkpointId}); + FileOutputStream outputStream = new FileOutputStream(new File(filePath)); + String input = checkpoint.getInput(); + IOUtils.write(input, outputStream); + IOUtils.closeQuietly(outputStream); + } + { // Standard Output File + String filePath = + String.format("%s/output#%s.txt", new Object[] {checkpointsFilePath, checkpointId}); + FileOutputStream outputStream = new FileOutputStream(new File(filePath)); + String output = checkpoint.getOutput(); + IOUtils.write(output, outputStream); + IOUtils.closeQuietly(outputStream); + } + } + } + + /** 自动注入的CheckpointMapper对象. 用于获取试题的测试点. */ + @Autowired private CheckpointMapper checkpointMapper; + + /** 测试点的存储目录. 用于存储测试点的输入输出数据. */ + @Value("${judger.checkpointDir}") + private String checkpointDirectory; } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/core/Runner.java b/judger/src/main/java/org/verwandlung/voj/judger/core/Runner.java index 149b3899..c15d574b 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/core/Runner.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/core/Runner.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -53,188 +53,213 @@ /** * 本地程序执行器, 用于执行本地应用程序. 包括编译器(gcc)以及用户提交的代码所编译出的程序. - * + * * @author Haozhe Xie */ @Component public class Runner { - /** - * 获取(用户)程序运行结果. - * - * @param submission - 评测记录对象 - * @param workDirectory - 编译生成结果的目录以及程序输出的目录 - * @param baseFileName - 待执行的应用程序文件名(不包含文件后缀) - * @param inputFilePath - 输入文件路径 - * @param outputFilePath - 输出文件路径 - * @return 一个包含程序运行结果的Map对象 - */ - public Map getRuntimeResult(Submission submission, String workDirectory, - String baseFileName, String inputFilePath, String outputFilePath) { - String commandLine = getCommandLine(submission, workDirectory, baseFileName); - int timeLimit = getTimeLimit(submission); - int memoryLimit = getMemoryLimit(submission); - - Map result = new HashMap<>(4, 1); - String runtimeResultSlug = "SE"; - int usedTime = 0; - int usedMemory = 0; - - try { - LOGGER.info(String.format("[Submission #%d] Start running with command %s (TimeLimit=%d, MemoryLimit=%s)", - new Object[] { submission.getSubmissionId(), commandLine, timeLimit, memoryLimit })); - Map runtimeResult = getRuntimeResult(commandLine, - systemUsername, systemPassword, inputFilePath, outputFilePath, - timeLimit, memoryLimit); - - int exitCode = (Integer) runtimeResult.get("exitCode"); - usedTime = (Integer) runtimeResult.get("usedTime"); - usedMemory = (Integer) runtimeResult.get("usedMemory"); - runtimeResultSlug = getRuntimeResultSlug(exitCode, timeLimit, usedTime, memoryLimit, usedMemory); - } catch ( Exception ex ) { - LOGGER.catching(ex); - } - - result.put("runtimeResult", runtimeResultSlug); - result.put("usedTime", usedTime); - result.put("usedMemory", usedMemory); - return result; - } - - /** - * 获取待执行的命令行. - * @param submission - 评测记录对象 - * @param workDirectory - 编译生成结果的目录以及程序输出的目录 - * @param baseFileName - 待执行的应用程序文件名(不包含文件后缀) - * @return 待执行的命令行 - */ - private String getCommandLine(Submission submission, - String workDirectory, String baseFileName) { - Language language = submission.getLanguage(); - String filePathWithoutExtension = String.format("%s/%s", - new Object[] {workDirectory, baseFileName}); - StringBuilder runCommand = new StringBuilder(language.getRunCommand() - .replaceAll("\\{filename\\}", filePathWithoutExtension)); - - if ( language.getLanguageName().equalsIgnoreCase("Java") ) { - int lastIndexOfSpace = runCommand.lastIndexOf("/"); - runCommand.setCharAt(lastIndexOfSpace, ' '); - } - return runCommand.toString(); - } - - /** - * 根据不同语言获取最大时间限制. - * @param submission - 评测记录对象 - * @return 最大时间限制 - */ - private int getTimeLimit(Submission submission) { - Language language = submission.getLanguage(); - int timeLimit = submission.getProblem().getTimeLimit(); - - if ( language.getLanguageName().equalsIgnoreCase("Java") ) { - timeLimit *= 2; - } - return timeLimit; - } - - /** - * 根据不同语言获取最大空间限制. - * @param submission - 评测记录对象 - * @return 最大空间限制 - */ - private int getMemoryLimit(Submission submission) { - int memoryLimit = submission.getProblem().getMemoryLimit(); - return memoryLimit; - } - - /** - * 根据JNI返回的结果封装评测结果. - * @param exitCode - 程序退出状态位 - * @param timeLimit - 最大时间限制 - * @param timeUsed - 程序运行所用时间 - * @param memoryLimit - 最大空间限制 - * @param memoryUsed - 程序运行所用空间(最大值) - * @return 程序运行结果的唯一英文缩写 - */ - private String getRuntimeResultSlug(int exitCode, int timeLimit, int timeUsed, int memoryLimit, int memoryUsed) { - if ( exitCode == 0 ) { - // Output will be compared in next stage - return "AC"; - } - if ( timeUsed >= timeLimit ) { - return "TLE"; - } - if ( memoryUsed >= memoryLimit ) { - return "MLE"; - } - return "RE"; - } - - /** - * 获取(编译)程序运行结果. - * @param commandLine - 待执行程序的命令行 - * @param inputFilePath - 输入文件路径(可为NULL) - * @param outputFilePath - 输出文件路径(可为NULL) - * @param timeLimit - 时间限制(单位ms, 0表示不限制) - * @param memoryLimit - 内存限制(单位KB, 0表示不限制) - * @return 一个包含程序运行结果的Map对象 - */ - public Map getRuntimeResult(String commandLine, - String inputFilePath, String outputFilePath, int timeLimit, - int memoryLimit) { - Map result = null; - try { - result = getRuntimeResult(commandLine, systemUsername, systemPassword, - inputFilePath, outputFilePath, timeLimit, memoryLimit); - } catch ( Exception ex ) { - LOGGER.catching(ex); - } - return result; - } - - /** - * 获取程序运行结果. - * @param commandLine - 待执行程序的命令行 - * @param systemUsername - 登录操作系统的用户名 - * @param systemPassword - 登录操作系统的密码 - * @param inputFilePath - 输入文件路径(可为NULL) - * @param outputFilePath - 输出文件路径(可为NULL) - * @param timeLimit - 时间限制(单位ms, 0表示不限制) - * @param memoryLimit - 内存限制(单位KB, 0表示不限制) - * @return 一个包含程序运行结果的Map对象 - */ - public native Map getRuntimeResult(String commandLine, - String systemUsername, String systemPassword, String inputFilePath, - String outputFilePath, int timeLimit, int memoryLimit); - - /** - * 登录操作系统的用户名. - * 为了安全, 我们建议评测程序以低权限的用户运行. - */ - @Value("${system.username}") - private String systemUsername; - - /** - * 登录操作系统的密码. - * 为了安全, 我们建议评测程序以低权限的用户运行. - */ - @Value("${system.password}") - private String systemPassword; - - /** - * 日志记录器. - */ - private static final Logger LOGGER = LogManager.getLogger(Runner.class); - - /** - * Load Native Library. - */ - static { - try { - NativeLibraryLoader.loadLibrary("JudgerCore"); - } catch (Exception ex) { - ex.printStackTrace(); - LOGGER.catching(ex); - } - } + /** + * 获取(用户)程序运行结果. + * + * @param submission - 评测记录对象 + * @param workDirectory - 编译生成结果的目录以及程序输出的目录 + * @param baseFileName - 待执行的应用程序文件名(不包含文件后缀) + * @param inputFilePath - 输入文件路径 + * @param outputFilePath - 输出文件路径 + * @return 一个包含程序运行结果的Map对象 + */ + public Map getRuntimeResult( + Submission submission, + String workDirectory, + String baseFileName, + String inputFilePath, + String outputFilePath) { + String commandLine = getCommandLine(submission, workDirectory, baseFileName); + int timeLimit = getTimeLimit(submission); + int memoryLimit = getMemoryLimit(submission); + + Map result = new HashMap<>(4, 1); + String runtimeResultSlug = "SE"; + int usedTime = 0; + int usedMemory = 0; + + try { + LOGGER.info( + String.format( + "[Submission #%d] Start running with command %s (TimeLimit=%d, MemoryLimit=%s)", + new Object[] {submission.getSubmissionId(), commandLine, timeLimit, memoryLimit})); + Map runtimeResult = + getRuntimeResult( + commandLine, + systemUsername, + systemPassword, + inputFilePath, + outputFilePath, + timeLimit, + memoryLimit); + + int exitCode = (Integer) runtimeResult.get("exitCode"); + usedTime = (Integer) runtimeResult.get("usedTime"); + usedMemory = (Integer) runtimeResult.get("usedMemory"); + runtimeResultSlug = + getRuntimeResultSlug(exitCode, timeLimit, usedTime, memoryLimit, usedMemory); + } catch (Exception ex) { + LOGGER.catching(ex); + } + + result.put("runtimeResult", runtimeResultSlug); + result.put("usedTime", usedTime); + result.put("usedMemory", usedMemory); + return result; + } + + /** + * 获取待执行的命令行. + * + * @param submission - 评测记录对象 + * @param workDirectory - 编译生成结果的目录以及程序输出的目录 + * @param baseFileName - 待执行的应用程序文件名(不包含文件后缀) + * @return 待执行的命令行 + */ + private String getCommandLine(Submission submission, String workDirectory, String baseFileName) { + Language language = submission.getLanguage(); + String filePathWithoutExtension = + String.format("%s/%s", new Object[] {workDirectory, baseFileName}); + StringBuilder runCommand = + new StringBuilder( + language.getRunCommand().replaceAll("\\{filename\\}", filePathWithoutExtension)); + + if (language.getLanguageName().equalsIgnoreCase("Java")) { + int lastIndexOfSpace = runCommand.lastIndexOf("/"); + runCommand.setCharAt(lastIndexOfSpace, ' '); + } + return runCommand.toString(); + } + + /** + * 根据不同语言获取最大时间限制. + * + * @param submission - 评测记录对象 + * @return 最大时间限制 + */ + private int getTimeLimit(Submission submission) { + Language language = submission.getLanguage(); + int timeLimit = submission.getProblem().getTimeLimit(); + + if (language.getLanguageName().equalsIgnoreCase("Java")) { + timeLimit *= 2; + } + return timeLimit; + } + + /** + * 根据不同语言获取最大空间限制. + * + * @param submission - 评测记录对象 + * @return 最大空间限制 + */ + private int getMemoryLimit(Submission submission) { + int memoryLimit = submission.getProblem().getMemoryLimit(); + return memoryLimit; + } + + /** + * 根据JNI返回的结果封装评测结果. + * + * @param exitCode - 程序退出状态位 + * @param timeLimit - 最大时间限制 + * @param timeUsed - 程序运行所用时间 + * @param memoryLimit - 最大空间限制 + * @param memoryUsed - 程序运行所用空间(最大值) + * @return 程序运行结果的唯一英文缩写 + */ + private String getRuntimeResultSlug( + int exitCode, int timeLimit, int timeUsed, int memoryLimit, int memoryUsed) { + if (exitCode == 0) { + // Output will be compared in next stage + return "AC"; + } + if (timeUsed >= timeLimit) { + return "TLE"; + } + if (memoryUsed >= memoryLimit) { + return "MLE"; + } + return "RE"; + } + + /** + * 获取(编译)程序运行结果. + * + * @param commandLine - 待执行程序的命令行 + * @param inputFilePath - 输入文件路径(可为NULL) + * @param outputFilePath - 输出文件路径(可为NULL) + * @param timeLimit - 时间限制(单位ms, 0表示不限制) + * @param memoryLimit - 内存限制(单位KB, 0表示不限制) + * @return 一个包含程序运行结果的Map对象 + */ + public Map getRuntimeResult( + String commandLine, + String inputFilePath, + String outputFilePath, + int timeLimit, + int memoryLimit) { + Map result = null; + try { + result = + getRuntimeResult( + commandLine, + systemUsername, + systemPassword, + inputFilePath, + outputFilePath, + timeLimit, + memoryLimit); + } catch (Exception ex) { + LOGGER.catching(ex); + } + return result; + } + + /** + * 获取程序运行结果. + * + * @param commandLine - 待执行程序的命令行 + * @param systemUsername - 登录操作系统的用户名 + * @param systemPassword - 登录操作系统的密码 + * @param inputFilePath - 输入文件路径(可为NULL) + * @param outputFilePath - 输出文件路径(可为NULL) + * @param timeLimit - 时间限制(单位ms, 0表示不限制) + * @param memoryLimit - 内存限制(单位KB, 0表示不限制) + * @return 一个包含程序运行结果的Map对象 + */ + public native Map getRuntimeResult( + String commandLine, + String systemUsername, + String systemPassword, + String inputFilePath, + String outputFilePath, + int timeLimit, + int memoryLimit); + + /** 登录操作系统的用户名. 为了安全, 我们建议评测程序以低权限的用户运行. */ + @Value("${system.username}") + private String systemUsername; + + /** 登录操作系统的密码. 为了安全, 我们建议评测程序以低权限的用户运行. */ + @Value("${system.password}") + private String systemPassword; + + /** 日志记录器. */ + private static final Logger LOGGER = LogManager.getLogger(Runner.class); + + /** Load Native Library. */ + static { + try { + NativeLibraryLoader.loadLibrary("JudgerCore"); + } catch (Exception ex) { + ex.printStackTrace(); + LOGGER.catching(ex); + } + } } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/exception/CreateDirectoryException.java b/judger/src/main/java/org/verwandlung/voj/judger/exception/CreateDirectoryException.java index b22426a5..482abf6c 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/exception/CreateDirectoryException.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/exception/CreateDirectoryException.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -40,22 +40,20 @@ package org.verwandlung.voj.judger.exception; /** - * 创建文件夹失败的IO异常. - * 当java.io.File.File.mkdirs()返回false时被抛出. - * + * 创建文件夹失败的IO异常. 当java.io.File.File.mkdirs()返回false时被抛出. + * * @author Haozhe Xie */ public class CreateDirectoryException extends Exception { - /** - * IOException的构造函数. - * @param message - 错误消息 - */ - public CreateDirectoryException(String message) { - super(message); - } - - /** - * 唯一的序列化标识符. - */ - private static final long serialVersionUID = 7430055519184434330L; + /** + * IOException的构造函数. + * + * @param message - 错误消息 + */ + public CreateDirectoryException(String message) { + super(message); + } + + /** 唯一的序列化标识符. */ + private static final long serialVersionUID = 7430055519184434330L; } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/exception/IllgealSubmissionException.java b/judger/src/main/java/org/verwandlung/voj/judger/exception/IllgealSubmissionException.java index 8df191ba..98447e0c 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/exception/IllgealSubmissionException.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/exception/IllgealSubmissionException.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -40,22 +40,20 @@ package org.verwandlung.voj.judger.exception; /** - * 无效的提交记录异常. - * 当getSubmission(long)操作返回null时被抛出. - * + * 无效的提交记录异常. 当getSubmission(long)操作返回null时被抛出. + * * @author Haozhe Xie */ public class IllgealSubmissionException extends Exception { - /** - * IllgealSubmissionException的构造函数. - * @param message - 错误消息 - */ - public IllgealSubmissionException(String message) { - super(message); - } + /** + * IllgealSubmissionException的构造函数. + * + * @param message - 错误消息 + */ + public IllgealSubmissionException(String message) { + super(message); + } - /** - * 唯一的序列化标识符. - */ - private static final long serialVersionUID = -9019235951964656553L; + /** 唯一的序列化标识符. */ + private static final long serialVersionUID = -9019235951964656553L; } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/mapper/CheckpointMapper.java b/judger/src/main/java/org/verwandlung/voj/judger/mapper/CheckpointMapper.java index 51c30a48..ba4fb2a2 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/mapper/CheckpointMapper.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/mapper/CheckpointMapper.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -52,24 +52,26 @@ /** * Checkpoint Data Access Object. + * * @author Haozhe Xie */ @CacheNamespace(implementation = org.mybatis.caches.ehcache.EhcacheCache.class) public interface CheckpointMapper { - /** - * 获取某个试题的全部测试点. - * @param problemId - 试题的唯一标识符 - * @return 某个试题的全部测试点 - */ - @Select("SELECT * FROM voj_problem_checkpoints WHERE problem_id = #{problemId}") - @Options(useCache = true) - @Results({ - @Result(property = "problemId", column = "problem_id"), - @Result(property = "checkpointId", column = "checkpoint_id"), - @Result(property = "isExactlyMatch", column = "checkpoint_exactly_match"), - @Result(property = "score", column = "checkpoint_score"), - @Result(property = "input", column = "checkpoint_input"), - @Result(property = "output", column = "checkpoint_output"), - }) - List getCheckpointsUsingProblemId(@Param("problemId") long problemId); + /** + * 获取某个试题的全部测试点. + * + * @param problemId - 试题的唯一标识符 + * @return 某个试题的全部测试点 + */ + @Select("SELECT * FROM voj_problem_checkpoints WHERE problem_id = #{problemId}") + @Options(useCache = true) + @Results({ + @Result(property = "problemId", column = "problem_id"), + @Result(property = "checkpointId", column = "checkpoint_id"), + @Result(property = "isExactlyMatch", column = "checkpoint_exactly_match"), + @Result(property = "score", column = "checkpoint_score"), + @Result(property = "input", column = "checkpoint_input"), + @Result(property = "output", column = "checkpoint_output"), + }) + List getCheckpointsUsingProblemId(@Param("problemId") long problemId); } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/mapper/JudgeResultMapper.java b/judger/src/main/java/org/verwandlung/voj/judger/mapper/JudgeResultMapper.java index 51e00f42..528cc47d 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/mapper/JudgeResultMapper.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/mapper/JudgeResultMapper.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -52,35 +52,37 @@ /** * JudgeResult Data Access Object. + * * @author Haozhe Xie */ @CacheNamespace(implementation = org.mybatis.caches.ehcache.EhcacheCache.class) public interface JudgeResultMapper { - /** - * 通过评测结果的唯一标识符获取评测结果对象. - * @return 预期的评测结果对象或空引用 - */ - @Select("SELECT * FROM voj_judge_results") - @Options(useCache = true) - @Results({ - @Result(property = "judgeResultId", column = "judge_result_id"), - @Result(property = "judgeResultSlug", column = "judge_result_slug"), - @Result(property = "judgeResultName", column = "judge_result_name") - }) - List getAllJudgeResults(); - - /** - * 通过评测结果的唯一英文缩写获取评测结果对象. - * @param judgeResultSlug - 评测结果的唯一英文缩写 - * @return 预期的评测结果对象或空引用 - */ - @Select("SELECT * FROM voj_judge_results WHERE judge_result_slug = #{judgeResultSlug}") - @Options(useCache = true) - @Results({ - @Result(property = "judgeResultId", column = "judge_result_id"), - @Result(property = "judgeResultSlug", column = "judge_result_slug"), - @Result(property = "judgeResultName", column = "judge_result_name") - }) - JudgeResult getJudgeResultUsingSlug(@Param("judgeResultSlug") String judgeResultSlug); + /** + * 通过评测结果的唯一标识符获取评测结果对象. + * + * @return 预期的评测结果对象或空引用 + */ + @Select("SELECT * FROM voj_judge_results") + @Options(useCache = true) + @Results({ + @Result(property = "judgeResultId", column = "judge_result_id"), + @Result(property = "judgeResultSlug", column = "judge_result_slug"), + @Result(property = "judgeResultName", column = "judge_result_name") + }) + List getAllJudgeResults(); + /** + * 通过评测结果的唯一英文缩写获取评测结果对象. + * + * @param judgeResultSlug - 评测结果的唯一英文缩写 + * @return 预期的评测结果对象或空引用 + */ + @Select("SELECT * FROM voj_judge_results WHERE judge_result_slug = #{judgeResultSlug}") + @Options(useCache = true) + @Results({ + @Result(property = "judgeResultId", column = "judge_result_id"), + @Result(property = "judgeResultSlug", column = "judge_result_slug"), + @Result(property = "judgeResultName", column = "judge_result_name") + }) + JudgeResult getJudgeResultUsingSlug(@Param("judgeResultSlug") String judgeResultSlug); } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/mapper/LanguageMapper.java b/judger/src/main/java/org/verwandlung/voj/judger/mapper/LanguageMapper.java index 844c588f..00f5f40b 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/mapper/LanguageMapper.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/mapper/LanguageMapper.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -52,54 +52,58 @@ /** * Language Data Access Object. + * * @author Haozhe Xie */ @CacheNamespace(implementation = org.mybatis.caches.ehcache.EhcacheCache.class) public interface LanguageMapper { - /** - * 通过编程语言的唯一标识符获取编程语言对象. - * @param languageId - 编程语言的唯一标识符 - * @return 预期的编程语言对象或空引用 - */ - @Select("SELECT * FROM voj_languages WHERE language_id = #{languageId}") - @Options(useCache = true) - @Results({ - @Result(property = "languageId", column = "language_id"), - @Result(property = "languageSlug", column = "language_slug"), - @Result(property = "languageName", column = "language_name"), - @Result(property = "compileCommand", column = "language_compile_command"), - @Result(property = "runCommand", column = "language_run_command"), - }) - Language getLanguageUsingId(@Param("languageId") int languageId); - - /** - * 通过编程语言的唯一英文缩写获取编程语言对象. - * @param languageSlug - 编程语言的唯一英文缩写 - * @return 预期的编程语言对象或空引用 - */ - @Select("SELECT * FROM voj_languages WHERE language_slug = #{languageSlug}") - @Options(useCache = true) - @Results({ - @Result(property = "languageId", column = "language_id"), - @Result(property = "languageSlug", column = "language_slug"), - @Result(property = "languageName", column = "language_name"), - @Result(property = "compileCommand", column = "language_compile_command"), - @Result(property = "runCommand", column = "language_run_command"), - }) - Language getLanguageUsingSlug(@Param("languageSlug") String languageSlug); - - /** - * 获取支持的编程语言. - * @return 编程语言列表(List对象) - */ - @Select("SELECT * FROM voj_languages") - @Options(useCache = true) - @Results({ - @Result(property = "languageId", column = "language_id"), - @Result(property = "languageSlug", column = "language_slug"), - @Result(property = "languageName", column = "language_name"), - @Result(property = "compileCommand", column = "language_compile_command"), - @Result(property = "runCommand", column = "language_run_command"), - }) - List getAllLanguages(); + /** + * 通过编程语言的唯一标识符获取编程语言对象. + * + * @param languageId - 编程语言的唯一标识符 + * @return 预期的编程语言对象或空引用 + */ + @Select("SELECT * FROM voj_languages WHERE language_id = #{languageId}") + @Options(useCache = true) + @Results({ + @Result(property = "languageId", column = "language_id"), + @Result(property = "languageSlug", column = "language_slug"), + @Result(property = "languageName", column = "language_name"), + @Result(property = "compileCommand", column = "language_compile_command"), + @Result(property = "runCommand", column = "language_run_command"), + }) + Language getLanguageUsingId(@Param("languageId") int languageId); + + /** + * 通过编程语言的唯一英文缩写获取编程语言对象. + * + * @param languageSlug - 编程语言的唯一英文缩写 + * @return 预期的编程语言对象或空引用 + */ + @Select("SELECT * FROM voj_languages WHERE language_slug = #{languageSlug}") + @Options(useCache = true) + @Results({ + @Result(property = "languageId", column = "language_id"), + @Result(property = "languageSlug", column = "language_slug"), + @Result(property = "languageName", column = "language_name"), + @Result(property = "compileCommand", column = "language_compile_command"), + @Result(property = "runCommand", column = "language_run_command"), + }) + Language getLanguageUsingSlug(@Param("languageSlug") String languageSlug); + + /** + * 获取支持的编程语言. + * + * @return 编程语言列表(List对象) + */ + @Select("SELECT * FROM voj_languages") + @Options(useCache = true) + @Results({ + @Result(property = "languageId", column = "language_id"), + @Result(property = "languageSlug", column = "language_slug"), + @Result(property = "languageName", column = "language_name"), + @Result(property = "compileCommand", column = "language_compile_command"), + @Result(property = "runCommand", column = "language_run_command"), + }) + List getAllLanguages(); } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/mapper/ProblemMapper.java b/judger/src/main/java/org/verwandlung/voj/judger/mapper/ProblemMapper.java index 5b8e75bc..4c16e184 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/mapper/ProblemMapper.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/mapper/ProblemMapper.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -50,31 +50,33 @@ /** * Problem Data Access Object. + * * @author Haozhe Xie */ @CacheNamespace(implementation = org.mybatis.caches.ehcache.EhcacheCache.class) public interface ProblemMapper { - /** - * 通过试题唯一标识符获取试题对象. - * @param problemId - 试题的唯一标识符 - * @return 一个试题对象 - */ - @Select("SELECT * FROM voj_problems WHERE problem_id = #{problemId}") - @Options(useCache = true) - @Results({ - @Result(property = "problemId", column = "problem_id"), - @Result(property = "isPublic", column = "problem_is_public"), - @Result(property = "problemName", column = "problem_name"), - @Result(property = "totalSubmission", column = "total_submission"), - @Result(property = "acceptedSubmission", column = "accepted_submission"), - @Result(property = "timeLimit", column = "problem_time_limit"), - @Result(property = "memoryLimit", column = "problem_memory_limit"), - @Result(property = "description", column = "problem_description"), - @Result(property = "inputFormat", column = "problem_input_format"), - @Result(property = "outputFormat", column = "problem_output_format"), - @Result(property = "sampleInput", column = "problem_sample_input"), - @Result(property = "sampleOutput", column = "problem_sample_output"), - @Result(property = "hint", column = "problem_hint") - }) - Problem getProblem(@Param("problemId") long problemId); + /** + * 通过试题唯一标识符获取试题对象. + * + * @param problemId - 试题的唯一标识符 + * @return 一个试题对象 + */ + @Select("SELECT * FROM voj_problems WHERE problem_id = #{problemId}") + @Options(useCache = true) + @Results({ + @Result(property = "problemId", column = "problem_id"), + @Result(property = "isPublic", column = "problem_is_public"), + @Result(property = "problemName", column = "problem_name"), + @Result(property = "totalSubmission", column = "total_submission"), + @Result(property = "acceptedSubmission", column = "accepted_submission"), + @Result(property = "timeLimit", column = "problem_time_limit"), + @Result(property = "memoryLimit", column = "problem_memory_limit"), + @Result(property = "description", column = "problem_description"), + @Result(property = "inputFormat", column = "problem_input_format"), + @Result(property = "outputFormat", column = "problem_output_format"), + @Result(property = "sampleInput", column = "problem_sample_input"), + @Result(property = "sampleOutput", column = "problem_sample_output"), + @Result(property = "hint", column = "problem_hint") + }) + Problem getProblem(@Param("problemId") long problemId); } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/mapper/SubmissionMapper.java b/judger/src/main/java/org/verwandlung/voj/judger/mapper/SubmissionMapper.java index 64aba37c..598a916f 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/mapper/SubmissionMapper.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/mapper/SubmissionMapper.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -54,38 +54,55 @@ /** * Submission Data Access Object. + * * @author Haozhe Xie */ @CacheNamespace(implementation = org.mybatis.caches.ehcache.EhcacheCache.class) public interface SubmissionMapper { - /** - * 通过评测记录唯一标识符获取试题对象. - * @param submissionId - 评测记录的唯一标识符 - * @return 一个评测记录对象 - */ - @Select("SELECT * FROM voj_submissions WHERE submission_id = #{submissionId}") - @Options(useCache = true) - @Results({ - @Result(property = "submissionId", column = "submission_id"), - @Result(property = "problem", column = "problem_id", javaType = Problem.class, one = @One(select="org.verwandlung.voj.judger.mapper.ProblemMapper.getProblem")), - @Result(property = "uid", column = "uid"), - @Result(property = "language", column = "language_id", javaType=Language.class, one = @One(select="org.verwandlung.voj.judger.mapper.LanguageMapper.getLanguageUsingId")), - @Result(property = "submitTime", column = "submission_submit_time"), - @Result(property = "executeTime", column = "submission_execute_time"), - @Result(property = "usedTime", column = "submission_used_time"), - @Result(property = "usedMemory", column = "submission_used_memory"), - @Result(property = "judgeResultSlug", column = "submission_judge_result"), - @Result(property = "judgeScore", column = "submission_judge_score"), - @Result(property = "judgeLog", column = "submission_judge_log"), - @Result(property = "code", column = "submission_code"), - }) - Submission getSubmission(@Param("submissionId") long submissionId); - - /** - * 更新提交记录. - * @param submission - 待更新的提交记录对象 - */ - @Update("UPDATE voj_submissions SET problem_id = #{problem.problemId}, uid = #{uid}, language_id = #{language.languageId}, submission_submit_time = #{submitTime}, submission_execute_time = #{executeTime}, submission_used_time = #{usedTime}, submission_used_memory = #{usedMemory}, submission_judge_result = #{judgeResultSlug}, submission_judge_score = #{judgeScore}, submission_judge_log = #{judgeLog}, submission_code = #{code} WHERE submission_id = #{submissionId}") - @Options(flushCache = Options.FlushCachePolicy.TRUE) - void updateSubmission(Submission submission); + /** + * 通过评测记录唯一标识符获取试题对象. + * + * @param submissionId - 评测记录的唯一标识符 + * @return 一个评测记录对象 + */ + @Select("SELECT * FROM voj_submissions WHERE submission_id = #{submissionId}") + @Options(useCache = true) + @Results({ + @Result(property = "submissionId", column = "submission_id"), + @Result( + property = "problem", + column = "problem_id", + javaType = Problem.class, + one = @One(select = "org.verwandlung.voj.judger.mapper.ProblemMapper.getProblem")), + @Result(property = "uid", column = "uid"), + @Result( + property = "language", + column = "language_id", + javaType = Language.class, + one = @One(select = "org.verwandlung.voj.judger.mapper.LanguageMapper.getLanguageUsingId")), + @Result(property = "submitTime", column = "submission_submit_time"), + @Result(property = "executeTime", column = "submission_execute_time"), + @Result(property = "usedTime", column = "submission_used_time"), + @Result(property = "usedMemory", column = "submission_used_memory"), + @Result(property = "judgeResultSlug", column = "submission_judge_result"), + @Result(property = "judgeScore", column = "submission_judge_score"), + @Result(property = "judgeLog", column = "submission_judge_log"), + @Result(property = "code", column = "submission_code"), + }) + Submission getSubmission(@Param("submissionId") long submissionId); + + /** + * 更新提交记录. + * + * @param submission - 待更新的提交记录对象 + */ + @Update( + "UPDATE voj_submissions SET problem_id = #{problem.problemId}, uid = #{uid}, language_id =" + + " #{language.languageId}, submission_submit_time = #{submitTime}," + + " submission_execute_time = #{executeTime}, submission_used_time = #{usedTime}," + + " submission_used_memory = #{usedMemory}, submission_judge_result = #{judgeResultSlug}," + + " submission_judge_score = #{judgeScore}, submission_judge_log = #{judgeLog}," + + " submission_code = #{code} WHERE submission_id = #{submissionId}") + @Options(flushCache = Options.FlushCachePolicy.TRUE) + void updateSubmission(Submission submission); } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/mapper/UserGroupMapper.java b/judger/src/main/java/org/verwandlung/voj/judger/mapper/UserGroupMapper.java index 75a6c5d9..6af87603 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/mapper/UserGroupMapper.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/mapper/UserGroupMapper.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -50,22 +50,23 @@ /** * UserGroup Data Access Object. - * + * * @author Haozhe Xie */ @CacheNamespace(implementation = org.mybatis.caches.ehcache.EhcacheCache.class) public interface UserGroupMapper { - /** - * 通过用户组的唯一标识符获取用户组对象. - * @param userGroupId - 用户组的唯一标识符 - * @return 预期的用户组对象或空引用 - */ - @Select("SELECT * FROM voj_user_groups WHERE user_group_id = #{userGroupId}") - @Options(useCache = true) - @Results({ - @Result(property = "userGroupId", column = "user_group_id"), - @Result(property = "userGroupSlug", column = "user_group_slug"), - @Result(property = "userGroupName", column = "user_group_name") - }) - UserGroup getUserGroupUsingId(@Param("userGroupId") int userGroupId); + /** + * 通过用户组的唯一标识符获取用户组对象. + * + * @param userGroupId - 用户组的唯一标识符 + * @return 预期的用户组对象或空引用 + */ + @Select("SELECT * FROM voj_user_groups WHERE user_group_id = #{userGroupId}") + @Options(useCache = true) + @Results({ + @Result(property = "userGroupId", column = "user_group_id"), + @Result(property = "userGroupSlug", column = "user_group_slug"), + @Result(property = "userGroupName", column = "user_group_name") + }) + UserGroup getUserGroupUsingId(@Param("userGroupId") int userGroupId); } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/mapper/UserMapper.java b/judger/src/main/java/org/verwandlung/voj/judger/mapper/UserMapper.java index 83d9b992..a53d1029 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/mapper/UserMapper.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/mapper/UserMapper.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -53,21 +53,36 @@ /** * User Data Access Object. - * + * * @author Haozhe Xie */ @CacheNamespace(implementation = org.mybatis.caches.ehcache.EhcacheCache.class) public interface UserMapper { - /** - * 通过用户名获取用户对象. - * @param username - 用户名 - * @return 预期的用户对象或空引用 - */ - @Select("SELECT * FROM voj_users WHERE username = #{username}") - @Options(useCache = false) - @Results(value = { - @Result(property = "userGroup", column = "user_group_id", javaType = UserGroup.class, one = @One(select="org.verwandlung.voj.judger.mapper.UserGroupMapper.getUserGroupUsingId")), - @Result(property = "preferLanguage", column = "prefer_language_id", javaType = Language.class, one = @One(select="org.verwandlung.voj.judger.mapper.LanguageMapper.getLanguageUsingId")) - }) - User getUserUsingUsername(@Param("username") String username); + /** + * 通过用户名获取用户对象. + * + * @param username - 用户名 + * @return 预期的用户对象或空引用 + */ + @Select("SELECT * FROM voj_users WHERE username = #{username}") + @Options(useCache = false) + @Results( + value = { + @Result( + property = "userGroup", + column = "user_group_id", + javaType = UserGroup.class, + one = + @One( + select = + "org.verwandlung.voj.judger.mapper.UserGroupMapper.getUserGroupUsingId")), + @Result( + property = "preferLanguage", + column = "prefer_language_id", + javaType = Language.class, + one = + @One( + select = "org.verwandlung.voj.judger.mapper.LanguageMapper.getLanguageUsingId")) + }) + User getUserUsingUsername(@Param("username") String username); } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/messenger/MessageReceiver.java b/judger/src/main/java/org/verwandlung/voj/judger/messenger/MessageReceiver.java index a656741d..c4beb1a3 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/messenger/MessageReceiver.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/messenger/MessageReceiver.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -53,54 +53,48 @@ /** * 消息接收服务. + * * @author Haozhe Xie */ @Component public class MessageReceiver implements MessageListener { - /* (non-Javadoc) - * @see javax.jms.MessageListener#onMessage(javax.jms.Message) - */ - public void onMessage(Message message) { - if ( message instanceof MapMessage ) { - final MapMessage mapMessage = (MapMessage) message; - - try { - String event = mapMessage.getString("event"); - - if ( "SubmissionCreated".equals(event) ) { - newSubmissionHandler(mapMessage); - } else { - LOGGER.warn(String.format("Unknown Event Received. [Event = %s]", - new Object[] { event })); - } - } catch (Exception ex) { - LOGGER.catching(ex); - } - } - } - - /** - * 处理新提交请求. - * @param mapMessage - 消息队列中收到的MapMessage对象 - * @throws JMSException - */ - private void newSubmissionHandler(MapMessage mapMessage) throws JMSException { - long submissionId = mapMessage.getLong("submissionId"); - LOGGER.info(String.format("Received new submission task #%d", - new Object[] {submissionId})); - - dispatcher.onSubmissionCreated(submissionId); - } - - /** - * 自动注入的ApplicationDispatcher对象. - * 用于完成接收消息后的回调操作. - */ - @Autowired - private ApplicationDispatcher dispatcher; - - /** - * 日志记录器. - */ - private static final Logger LOGGER = LogManager.getLogger(MessageReceiver.class); + /* (non-Javadoc) + * @see javax.jms.MessageListener#onMessage(javax.jms.Message) + */ + public void onMessage(Message message) { + if (message instanceof MapMessage) { + final MapMessage mapMessage = (MapMessage) message; + + try { + String event = mapMessage.getString("event"); + + if ("SubmissionCreated".equals(event)) { + newSubmissionHandler(mapMessage); + } else { + LOGGER.warn(String.format("Unknown Event Received. [Event = %s]", new Object[] {event})); + } + } catch (Exception ex) { + LOGGER.catching(ex); + } + } + } + + /** + * 处理新提交请求. + * + * @param mapMessage - 消息队列中收到的MapMessage对象 + * @throws JMSException + */ + private void newSubmissionHandler(MapMessage mapMessage) throws JMSException { + long submissionId = mapMessage.getLong("submissionId"); + LOGGER.info(String.format("Received new submission task #%d", new Object[] {submissionId})); + + dispatcher.onSubmissionCreated(submissionId); + } + + /** 自动注入的ApplicationDispatcher对象. 用于完成接收消息后的回调操作. */ + @Autowired private ApplicationDispatcher dispatcher; + + /** 日志记录器. */ + private static final Logger LOGGER = LogManager.getLogger(MessageReceiver.class); } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/messenger/MessageSender.java b/judger/src/main/java/org/verwandlung/voj/judger/messenger/MessageSender.java index 3ec7ac7a..0c39ec6c 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/messenger/MessageSender.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/messenger/MessageSender.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -47,22 +47,20 @@ /** * 消息发送服务. + * * @author Haozhe Xie */ @Component public class MessageSender { - /** - * 发送消息至消息队列. - * @param mapMessage - Key-Value格式的消息 - */ - public void sendMessage(final Map mapMessage) { - jmsTemplate.convertAndSend(mapMessage); - } + /** + * 发送消息至消息队列. + * + * @param mapMessage - Key-Value格式的消息 + */ + public void sendMessage(final Map mapMessage) { + jmsTemplate.convertAndSend(mapMessage); + } - /** - * 自动注入的JmsTemplate对象. - * 用于发送消息至消息队列. - */ - @Autowired - private JmsTemplate jmsTemplate; -} \ No newline at end of file + /** 自动注入的JmsTemplate对象. 用于发送消息至消息队列. */ + @Autowired private JmsTemplate jmsTemplate; +} diff --git a/judger/src/main/java/org/verwandlung/voj/judger/model/Checkpoint.java b/judger/src/main/java/org/verwandlung/voj/judger/model/Checkpoint.java index 46c10888..f7a84c23 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/model/Checkpoint.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/model/Checkpoint.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -42,171 +42,174 @@ import java.io.Serializable; /** - * 程序测试点的Model. - * 对应数据库中的voj_problem_checkpoints数据表. - * + * 程序测试点的Model. 对应数据库中的voj_problem_checkpoints数据表. + * * @author Haozhe Xie */ public class Checkpoint implements Serializable { - /** - * CheckPoint的默认构造函数. - */ - public Checkpoint() { } - - /** - * CheckPoint的构造函数. - * @param problemId - 试题的唯一标识符 - * @param checkpointId - 测试点的唯一标识符 - * @param isExactlyMatch - 是否精确匹配测试点 - * @param score - 测试点的分值 - * @param input - 测试点的标准输入 - * @param output - 测试点的标准输出 - */ - public Checkpoint(long problemId, int checkpointId, boolean isExactlyMatch, int score, String input, String output) { - this.problemId = problemId; - this.checkpointId = checkpointId; - this.isExactlyMatch = isExactlyMatch; - this.score = score; - this.input = input; - this.output = output; - } - - /** - * 获取试题的唯一标识符. - * @return 试题的唯一标识符 - */ - public long getProblemId() { - return problemId; - } - - /** - * 设置试题的唯一标识符. - * @param problemId - 试题的唯一标识符 - */ - public void setProblemId(long problemId) { - this.problemId = problemId; - } - - /** - * 获取测试点的唯一标识符. - * @return 测试点的唯一标识符 - */ - public int getCheckpointId() { - return checkpointId; - } - - /** - * 设置测试点的唯一标识符. - * @param checkpointId - 测试点的唯一标识符 - */ - public void setCheckpointId(int checkpointId) { - this.checkpointId = checkpointId; - } - - /** - * 获取是否精确匹配测试点. - * @return 是否精确匹配测试点 - */ - public boolean isExactlyMatch() { - return isExactlyMatch; - } - - /** - * 设置精确匹配测试点. - * @param isExactlyMatch - 是否精确匹配测试点 - */ - public void setExactlyMatch(boolean isExactlyMatch) { - this.isExactlyMatch = isExactlyMatch; - } - - /** - * 获取测试点的分值. - * @return 测试点的分值 - */ - public int getScore() { - return score; - } - - /** - * 设置测试点的分值. - * @param score - 测试点的分值 - */ - public void setScore(int score) { - this.score = score; - } - - /** - * 获取测试点的输入. - * @return 测试点的输入 - */ - public String getInput() { - return input; - } - - /** - * 设置测试点的输入. - * @param input - 测试点的输入 - */ - public void setInput(String input) { - this.input = input; - } - - /** - * 获取测试点的输出. - * @return 测试点的输出 - */ - public String getOutput() { - return output; - } - - /** - * 设置测试点的输出. - * @param output - 测试点的输出 - */ - public void setOutput(String output) { - this.output = output; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - public String toString() { - return String.format("CheckPoint [ProblemId=%d, CheckpointId=%d, Score=%d]", - new Object[] {problemId, checkpointId, score}); - } - - /** - * 试题的唯一标识符. - */ - private long problemId; - - /** - * 测试点的唯一标识符. - */ - private int checkpointId; - - /** - * 是否精确匹配测试点. - */ - private boolean isExactlyMatch; - - /** - * 测试点分值. - */ - private int score; - - /** - * 测试点的标准输入. - */ - private String input; - - /** - * 测试点的标准输出. - */ - private String output; - - /** - * 唯一的序列化标识符. - */ - private static final long serialVersionUID = -8129670699537187948L; + /** CheckPoint的默认构造函数. */ + public Checkpoint() {} + + /** + * CheckPoint的构造函数. + * + * @param problemId - 试题的唯一标识符 + * @param checkpointId - 测试点的唯一标识符 + * @param isExactlyMatch - 是否精确匹配测试点 + * @param score - 测试点的分值 + * @param input - 测试点的标准输入 + * @param output - 测试点的标准输出 + */ + public Checkpoint( + long problemId, + int checkpointId, + boolean isExactlyMatch, + int score, + String input, + String output) { + this.problemId = problemId; + this.checkpointId = checkpointId; + this.isExactlyMatch = isExactlyMatch; + this.score = score; + this.input = input; + this.output = output; + } + + /** + * 获取试题的唯一标识符. + * + * @return 试题的唯一标识符 + */ + public long getProblemId() { + return problemId; + } + + /** + * 设置试题的唯一标识符. + * + * @param problemId - 试题的唯一标识符 + */ + public void setProblemId(long problemId) { + this.problemId = problemId; + } + + /** + * 获取测试点的唯一标识符. + * + * @return 测试点的唯一标识符 + */ + public int getCheckpointId() { + return checkpointId; + } + + /** + * 设置测试点的唯一标识符. + * + * @param checkpointId - 测试点的唯一标识符 + */ + public void setCheckpointId(int checkpointId) { + this.checkpointId = checkpointId; + } + + /** + * 获取是否精确匹配测试点. + * + * @return 是否精确匹配测试点 + */ + public boolean isExactlyMatch() { + return isExactlyMatch; + } + + /** + * 设置精确匹配测试点. + * + * @param isExactlyMatch - 是否精确匹配测试点 + */ + public void setExactlyMatch(boolean isExactlyMatch) { + this.isExactlyMatch = isExactlyMatch; + } + + /** + * 获取测试点的分值. + * + * @return 测试点的分值 + */ + public int getScore() { + return score; + } + + /** + * 设置测试点的分值. + * + * @param score - 测试点的分值 + */ + public void setScore(int score) { + this.score = score; + } + + /** + * 获取测试点的输入. + * + * @return 测试点的输入 + */ + public String getInput() { + return input; + } + + /** + * 设置测试点的输入. + * + * @param input - 测试点的输入 + */ + public void setInput(String input) { + this.input = input; + } + + /** + * 获取测试点的输出. + * + * @return 测试点的输出 + */ + public String getOutput() { + return output; + } + + /** + * 设置测试点的输出. + * + * @param output - 测试点的输出 + */ + public void setOutput(String output) { + this.output = output; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + public String toString() { + return String.format( + "CheckPoint [ProblemId=%d, CheckpointId=%d, Score=%d]", + new Object[] {problemId, checkpointId, score}); + } + + /** 试题的唯一标识符. */ + private long problemId; + + /** 测试点的唯一标识符. */ + private int checkpointId; + + /** 是否精确匹配测试点. */ + private boolean isExactlyMatch; + + /** 测试点分值. */ + private int score; + + /** 测试点的标准输入. */ + private String input; + + /** 测试点的标准输出. */ + private String output; + + /** 唯一的序列化标识符. */ + private static final long serialVersionUID = -8129670699537187948L; } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/model/JudgeResult.java b/judger/src/main/java/org/verwandlung/voj/judger/model/JudgeResult.java index e06cf335..b3683449 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/model/JudgeResult.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/model/JudgeResult.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -42,103 +42,100 @@ import java.io.Serializable; /** - * 程序评测结果的Model. - * 对应数据库中的voj_judge_results数据表. - * + * 程序评测结果的Model. 对应数据库中的voj_judge_results数据表. + * * @author Haozhe Xie */ public class JudgeResult implements Serializable { - /** - * 评测结果类的默认构造函数. - */ - public JudgeResult() { } - - /** - * 评测结果类的构造函数. - * @param judgeResultId - 评测结果的唯一标识符 - * @param judgeResultSlug - 评测结果的唯一英文缩写 - * @param judgeResultName - 评测结果的名称 - */ - public JudgeResult(int judgeResultId, String judgeResultSlug, String judgeResultName) { - this.judgeResultId = judgeResultId; - this.judgeResultSlug = judgeResultSlug; - this.judgeResultName = judgeResultName; - } - - /** - * 获取评测结果的唯一标识符. - * @return 评测结果的唯一标识符 - */ - public int getJudgeResultId() { - return judgeResultId; - } + /** 评测结果类的默认构造函数. */ + public JudgeResult() {} + + /** + * 评测结果类的构造函数. + * + * @param judgeResultId - 评测结果的唯一标识符 + * @param judgeResultSlug - 评测结果的唯一英文缩写 + * @param judgeResultName - 评测结果的名称 + */ + public JudgeResult(int judgeResultId, String judgeResultSlug, String judgeResultName) { + this.judgeResultId = judgeResultId; + this.judgeResultSlug = judgeResultSlug; + this.judgeResultName = judgeResultName; + } + + /** + * 获取评测结果的唯一标识符. + * + * @return 评测结果的唯一标识符 + */ + public int getJudgeResultId() { + return judgeResultId; + } + + /** + * 设置评测结果的唯一标识符. + * + * @param judgeResultId - 评测结果的唯一标识符 + */ + public void setJudgeResultId(int judgeResultId) { + this.judgeResultId = judgeResultId; + } + + /** + * 获取评测结果的唯一英文缩写. + * + * @return - 评测结果的唯一英文缩写 + */ + public String getJudgeResultSlug() { + return judgeResultSlug; + } + + /** + * 设置评测结果的唯一英文缩写. + * + * @param judgeResultSlug - 评测结果的唯一英文缩写 + */ + public void setJudgeResultSlug(String judgeResultSlug) { + this.judgeResultSlug = judgeResultSlug; + } - /** - * 设置评测结果的唯一标识符. - * @param judgeResultId - 评测结果的唯一标识符 - */ - public void setJudgeResultId(int judgeResultId) { - this.judgeResultId = judgeResultId; - } + /** + * 获取评测结果的名称. + * + * @return 评测结果的名称 + */ + public String getJudgeResultName() { + return judgeResultName; + } - /** - * 获取评测结果的唯一英文缩写. - * @return - 评测结果的唯一英文缩写 - */ - public String getJudgeResultSlug() { - return judgeResultSlug; - } + /** + * 设置评测结果的名称. + * + * @param judgeResultName - 评测结果的名称 + */ + public void setJudgeResultName(String judgeResultName) { + this.judgeResultName = judgeResultName; + } - /** - * 设置评测结果的唯一英文缩写. - * @param judgeResultSlug - 评测结果的唯一英文缩写 - */ - public void setJudgeResultSlug(String judgeResultSlug) { - this.judgeResultSlug = judgeResultSlug; - } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return String.format( + "JudgeResult [Id=%d, Slug=%s, Name=%s]", + new Object[] {judgeResultId, judgeResultSlug, judgeResultName}); + } - /** - * 获取评测结果的名称. - * @return 评测结果的名称 - */ - public String getJudgeResultName() { - return judgeResultName; - } + /** 评测结果的唯一标识符. */ + private int judgeResultId; - /** - * 设置评测结果的名称. - * @param judgeResultName - 评测结果的名称 - */ - public void setJudgeResultName(String judgeResultName) { - this.judgeResultName = judgeResultName; - } + /** 评测结果的英文唯一缩写. */ + private String judgeResultSlug; - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return String.format("JudgeResult [Id=%d, Slug=%s, Name=%s]", - new Object[] { judgeResultId, judgeResultSlug, judgeResultName }); - } + /** 评测结果的名称. */ + private String judgeResultName; - /** - * 评测结果的唯一标识符. - */ - private int judgeResultId; - - /** - * 评测结果的英文唯一缩写. - */ - private String judgeResultSlug; - - /** - * 评测结果的名称. - */ - private String judgeResultName; - - /** - * 唯一的序列化标识符. - */ - private static final long serialVersionUID = -1572920076997918781L; + /** 唯一的序列化标识符. */ + private static final long serialVersionUID = -1572920076997918781L; } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/model/Language.java b/judger/src/main/java/org/verwandlung/voj/judger/model/Language.java index 2d408cf7..b942ef9a 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/model/Language.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/model/Language.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -42,160 +42,164 @@ import java.io.Serializable; /** - * 编程语言的Model. - * 对应数据库中的voj_languages数据表. - * + * 编程语言的Model. 对应数据库中的voj_languages数据表. + * * @author Haozhe Xie */ public class Language implements Serializable { - /** - * 编程语言的默认构造函数. - */ - public Language() { } - - /** - * 编程语言的构造函数. - * @param languageSlug - 编程语言的英文缩写 - * @param languageName - 编程语言的名称 - * @param compileCommand - 编程语言的编译命令 - * @param runCommand - 编程语言对应程序执行命令 - */ - public Language(String languageSlug, String languageName, String compileCommand, String runCommand) { - this.languageSlug = languageSlug; - this.languageName = languageName; - this.compileCommand = compileCommand; - this.runCommand = runCommand; - } - - /** - * 编程语言的构造函数. - * @param languageId - 编程语言的唯一标识符 - * @param languageSlug - 编程语言的英文缩写 - * @param languageName - 编程语言的名称 - * @param compileCommand - 编程语言的编译命令 - * @param runCommand - 编程语言对应程序执行命令 - */ - public Language(int languageId, String languageSlug, String languageName, String compileCommand, String runCommand) { - this(languageSlug, languageName, compileCommand, runCommand); - this.languageId = languageId; - } - - /** - * 获取编程语言的唯一标识符. - * @return 编程语言的唯一标识符 - */ - public int getLanguageId() { - return languageId; - } - - /** - * 设置编程语言的唯一标识符. - * @param languageId - 编程语言的唯一标识符 - */ - public void setLanguageId(int languageId) { - this.languageId = languageId; - } - - /** - * 获取编程语言的英文缩写 - * @return 编程语言的英文缩写 - */ - public String getLanguageSlug() { - return languageSlug; - } - - /** - * 设置编程语言的英文缩写. - * @param languageSlug - 编程语言的英文缩写 - */ - public void setLanguageSlug(String languageSlug) { - this.languageSlug = languageSlug; - } - - /** - * 获取编程语言的名称. - * @return 编程语言的名称 - */ - public String getLanguageName() { - return languageName; - } - - /** - * 设置编程语言的名称. - * @param languageName - 编程语言的名称 - */ - public void setLanguageName(String languageName) { - this.languageName = languageName; - } - - /** - * 获取编程语言的编译命令. - * @return - */ - public String getCompileCommand() { - return compileCommand; - } - - /** - * 设置编程语言的编译命令. - * @param compileCommand - */ - public void setCompileCommand(String compileCommand) { - this.compileCommand = compileCommand; - } - - /** - * 获取编程语言的运行命令. - * @return 编程语言的运行命令 - */ - public String getRunCommand() { - return runCommand; - } - - /** - * 设置编程语言的运行命令. - * @param runCommand - 编程语言的运行命令 - */ - public void setRunCommand(String runCommand) { - this.runCommand = runCommand; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return String.format("Language [ID=%d, Slug=%s, Name=%s, CompileCommand=%s, runCommand=%s]", - new Object[] { languageId, languageSlug, languageName, compileCommand, runCommand }); - } - - /** - * 编程语言的唯一标识符. - */ - private int languageId; - - /** - * 编程语言的唯一英文简称. - */ - private String languageSlug; - - /** - * 编程语言的名称. - */ - private String languageName; - - /** - * 编程语言的编译命令. - */ - private String compileCommand; - - /** - * 编程语言的运行命令. - */ - private String runCommand; - - /** - * 唯一的序列化标识符 - */ - private static final long serialVersionUID = 9065824880175832696L; + /** 编程语言的默认构造函数. */ + public Language() {} + + /** + * 编程语言的构造函数. + * + * @param languageSlug - 编程语言的英文缩写 + * @param languageName - 编程语言的名称 + * @param compileCommand - 编程语言的编译命令 + * @param runCommand - 编程语言对应程序执行命令 + */ + public Language( + String languageSlug, String languageName, String compileCommand, String runCommand) { + this.languageSlug = languageSlug; + this.languageName = languageName; + this.compileCommand = compileCommand; + this.runCommand = runCommand; + } + + /** + * 编程语言的构造函数. + * + * @param languageId - 编程语言的唯一标识符 + * @param languageSlug - 编程语言的英文缩写 + * @param languageName - 编程语言的名称 + * @param compileCommand - 编程语言的编译命令 + * @param runCommand - 编程语言对应程序执行命令 + */ + public Language( + int languageId, + String languageSlug, + String languageName, + String compileCommand, + String runCommand) { + this(languageSlug, languageName, compileCommand, runCommand); + this.languageId = languageId; + } + + /** + * 获取编程语言的唯一标识符. + * + * @return 编程语言的唯一标识符 + */ + public int getLanguageId() { + return languageId; + } + + /** + * 设置编程语言的唯一标识符. + * + * @param languageId - 编程语言的唯一标识符 + */ + public void setLanguageId(int languageId) { + this.languageId = languageId; + } + + /** + * 获取编程语言的英文缩写 + * + * @return 编程语言的英文缩写 + */ + public String getLanguageSlug() { + return languageSlug; + } + + /** + * 设置编程语言的英文缩写. + * + * @param languageSlug - 编程语言的英文缩写 + */ + public void setLanguageSlug(String languageSlug) { + this.languageSlug = languageSlug; + } + + /** + * 获取编程语言的名称. + * + * @return 编程语言的名称 + */ + public String getLanguageName() { + return languageName; + } + + /** + * 设置编程语言的名称. + * + * @param languageName - 编程语言的名称 + */ + public void setLanguageName(String languageName) { + this.languageName = languageName; + } + + /** + * 获取编程语言的编译命令. + * + * @return + */ + public String getCompileCommand() { + return compileCommand; + } + + /** + * 设置编程语言的编译命令. + * + * @param compileCommand + */ + public void setCompileCommand(String compileCommand) { + this.compileCommand = compileCommand; + } + + /** + * 获取编程语言的运行命令. + * + * @return 编程语言的运行命令 + */ + public String getRunCommand() { + return runCommand; + } + + /** + * 设置编程语言的运行命令. + * + * @param runCommand - 编程语言的运行命令 + */ + public void setRunCommand(String runCommand) { + this.runCommand = runCommand; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return String.format( + "Language [ID=%d, Slug=%s, Name=%s, CompileCommand=%s, runCommand=%s]", + new Object[] {languageId, languageSlug, languageName, compileCommand, runCommand}); + } + + /** 编程语言的唯一标识符. */ + private int languageId; + + /** 编程语言的唯一英文简称. */ + private String languageSlug; + + /** 编程语言的名称. */ + private String languageName; + + /** 编程语言的编译命令. */ + private String compileCommand; + + /** 编程语言的运行命令. */ + private String runCommand; + + /** 唯一的序列化标识符 */ + private static final long serialVersionUID = 9065824880175832696L; } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/model/Problem.java b/judger/src/main/java/org/verwandlung/voj/judger/model/Problem.java index 72de1334..a8ae2b25 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/model/Problem.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/model/Problem.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -42,311 +42,347 @@ import java.io.Serializable; /** - * 试题的Model. - * 对应数据库中的voj_problems数据表. - * + * 试题的Model. 对应数据库中的voj_problems数据表. + * * @author Haozhe Xie */ public class Problem implements Serializable { - /** - * Problem的默认构造函数. - */ - public Problem() { } - - /** - * Problem的构造函数. - * @param isPublic - 试题是否公开 - * @param problemName - 试题的名称 - * @param timeLimit - 最大运行时间 - * @param memoryLimit - 最大运行内存 - * @param description - 试题描述 - * @param inputFormat - 试题输入格式描述 - * @param outputFormat - 试题输出描述 - * @param sampleInput - 试题样例输入 - * @param sampleOutput - 试题样例输出 - * @param hint - 试题提示 - */ - public Problem(boolean isPublic, String problemName, int timeLimit, int memoryLimit, - String description, String inputFormat, String outputFormat, - String sampleInput, String sampleOutput, String hint) { - this.isPublic = isPublic; - this.problemName = problemName; - this.timeLimit = timeLimit; - this.memoryLimit = memoryLimit; - this.description = description; - this.inputFormat = inputFormat; - this.outputFormat = outputFormat; - this.sampleInput = sampleInput; - this.sampleOutput = sampleOutput; - this.hint = hint; - } - - /** - * Problem类的构造函数. - * @param problemId - 试题唯一标识符 - * @param isPublic - 试题是否公开 - * @param problemName - 试题的名称 - * @param timeLimit - 最大运行时间 - * @param memoryLimit - 最大运行内存 - * @param description - 试题描述 - * @param inputFormat - 试题输入描述 - * @param outputFormat - 试题输出描述 - * @param sampleInput - 试题样例输入 - * @param sampleOutput - 试题样例输出 - * @param hint - 试题提示 - */ - public Problem(long problemId, boolean isPublic, String problemName, int timeLimit, - int memoryLimit, String description, String inputFormat, String outputFormat, - String sampleInput, String sampleOutput, String hint) { - this(isPublic, problemName, timeLimit, memoryLimit, description, inputFormat, outputFormat, sampleInput, sampleOutput, hint); - this.problemId = problemId; - } - - /** - * 获取试题唯一标识符. - * @return 试题唯一标识符 - */ - public long getProblemId() { - return problemId; - } - - /** - * 设置试题唯一标识符. - * @param problemId - 试题唯一标识符 - */ - public void setProblemId(long problemId) { - this.problemId = problemId; - } - - /** - * 获取试题是否公开的. - * @return 试题是否公开 - */ - public boolean isPublic() { - return isPublic; - } - - /** - * 设置试题是否公开. - * @param isPublic - 试题是否公开 - */ - public void setPublic(boolean isPublic) { - this.isPublic = isPublic; - } - - /** - * 获取试题名称. - * @return 试题名称 - */ - public String getProblemName() { - return problemName; - } - - /** - * 设置试题名称. - * @param problemName - 试题名称 - */ - public void setProblemName(String problemName) { - this.problemName = problemName; - } - - /** - * 获取最大运行时间. - * @return 最大运行时间 - */ - public int getTimeLimit() { - return timeLimit; - } - - /** - * 设置最大运行时间. - * @param timeLimit - 最大运行时间 - */ - public void setTimeLimit(int timeLimit) { - this.timeLimit = timeLimit; - } - - /** - * 获取最大运行内存. - * @return 最大运行内存 - */ - public int getMemoryLimit() { - return memoryLimit; - } - - /** - * 设置最大运行内存. - * @param memoryLimit - */ - public void setMemoryLimit(int memoryLimit) { - this.memoryLimit = memoryLimit; - } - - /** - * 获取试题描述. - * @return 试题描述 - */ - public String getDescription() { - return description; - } - - /** - * 设置试题描述. - * @param description - 试题描述 - */ - public void setDescription(String description) { - this.description = description; - } - - /** - * 获取输入格式描述. - * @return 输入格式描述 - */ - public String getInputFormat() { - return inputFormat; - } - - /** - * 设置输入格式描述. - * @param inputFormat - 输入格式描述 - */ - public void setInpuFormatt(String inputFormat) { - this.inputFormat = inputFormat; - } - - /** - * 获取输出格式描述. - * @return 输出格式描述 - */ - public String getOutputFormat() { - return outputFormat; - } - - /** - * 设置输出格式描述. - * @param outputFormat - 输出格式描述 - */ - public void setOutputFormat(String outputFormat) { - this.outputFormat = outputFormat; - } - - /** - * 获取样例输入. - * @return 样例输入 - */ - public String getSampleInput() { - return sampleInput; - } - - /** - * 设置样例输入. - * @param sampleInput - 样例输入 - */ - public void setSampleInput(String sampleInput) { - this.sampleInput = sampleInput; - } - - /** - * 获取样例输出. - * @return 样例输出 - */ - public String getSampleOutput() { - return sampleOutput; - } - - /** - * 设置样例输出. - * @param sampleOutput - 样例输出 - */ - public void setSampleOutput(String sampleOutput) { - this.sampleOutput = sampleOutput; - } - - /** - * 获取试题提示. - * @return 试题提示 - */ - public String getHint() { - return hint; - } - - /** - * 设置试题提示. - * @param hint - 试题提示 - */ - public void setHint(String hint) { - this.hint = hint; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return String.format("Problem: [ProblemID=%s, isPublic=%s, ProblemName=%s, TimeLimit=%s, " - + "MemoryLimit=%s, Description=%s, InputFormat=%s, OutputFormat=%s, " - + "SampleInput=%s, SampleOutput=%s, Hint=%s]", - new Object[] { problemId, isPublic, problemName, timeLimit, memoryLimit, - description, inputFormat, outputFormat, sampleInput, sampleOutput, hint}); - } - - /** - * 试题的唯一标识符. - */ - private long problemId; - - /** - * 试题是否公开. - */ - private boolean isPublic; - - /** - * 试题名称. - */ - private String problemName; - - /** - * 最大运行时间. - */ - private int timeLimit; - - /** - * 最大运行内存. - */ - private int memoryLimit; - - /** - * 试题描述. - */ - private String description; - - /** - * 输入格式. - */ - private String inputFormat; - - /** - * 输出格式. - */ - private String outputFormat; - - /** - * 样例输入. - */ - private String sampleInput; - - /** - * 样例输出. - */ - private String sampleOutput; - - /** - * 试题提示. - */ - private String hint; - - /** - * 唯一的序列化标识符. - */ - private static final long serialVersionUID = 4703482016721365341L; + /** Problem的默认构造函数. */ + public Problem() {} + + /** + * Problem的构造函数. + * + * @param isPublic - 试题是否公开 + * @param problemName - 试题的名称 + * @param timeLimit - 最大运行时间 + * @param memoryLimit - 最大运行内存 + * @param description - 试题描述 + * @param inputFormat - 试题输入格式描述 + * @param outputFormat - 试题输出描述 + * @param sampleInput - 试题样例输入 + * @param sampleOutput - 试题样例输出 + * @param hint - 试题提示 + */ + public Problem( + boolean isPublic, + String problemName, + int timeLimit, + int memoryLimit, + String description, + String inputFormat, + String outputFormat, + String sampleInput, + String sampleOutput, + String hint) { + this.isPublic = isPublic; + this.problemName = problemName; + this.timeLimit = timeLimit; + this.memoryLimit = memoryLimit; + this.description = description; + this.inputFormat = inputFormat; + this.outputFormat = outputFormat; + this.sampleInput = sampleInput; + this.sampleOutput = sampleOutput; + this.hint = hint; + } + + /** + * Problem类的构造函数. + * + * @param problemId - 试题唯一标识符 + * @param isPublic - 试题是否公开 + * @param problemName - 试题的名称 + * @param timeLimit - 最大运行时间 + * @param memoryLimit - 最大运行内存 + * @param description - 试题描述 + * @param inputFormat - 试题输入描述 + * @param outputFormat - 试题输出描述 + * @param sampleInput - 试题样例输入 + * @param sampleOutput - 试题样例输出 + * @param hint - 试题提示 + */ + public Problem( + long problemId, + boolean isPublic, + String problemName, + int timeLimit, + int memoryLimit, + String description, + String inputFormat, + String outputFormat, + String sampleInput, + String sampleOutput, + String hint) { + this( + isPublic, + problemName, + timeLimit, + memoryLimit, + description, + inputFormat, + outputFormat, + sampleInput, + sampleOutput, + hint); + this.problemId = problemId; + } + + /** + * 获取试题唯一标识符. + * + * @return 试题唯一标识符 + */ + public long getProblemId() { + return problemId; + } + + /** + * 设置试题唯一标识符. + * + * @param problemId - 试题唯一标识符 + */ + public void setProblemId(long problemId) { + this.problemId = problemId; + } + + /** + * 获取试题是否公开的. + * + * @return 试题是否公开 + */ + public boolean isPublic() { + return isPublic; + } + + /** + * 设置试题是否公开. + * + * @param isPublic - 试题是否公开 + */ + public void setPublic(boolean isPublic) { + this.isPublic = isPublic; + } + + /** + * 获取试题名称. + * + * @return 试题名称 + */ + public String getProblemName() { + return problemName; + } + + /** + * 设置试题名称. + * + * @param problemName - 试题名称 + */ + public void setProblemName(String problemName) { + this.problemName = problemName; + } + + /** + * 获取最大运行时间. + * + * @return 最大运行时间 + */ + public int getTimeLimit() { + return timeLimit; + } + + /** + * 设置最大运行时间. + * + * @param timeLimit - 最大运行时间 + */ + public void setTimeLimit(int timeLimit) { + this.timeLimit = timeLimit; + } + + /** + * 获取最大运行内存. + * + * @return 最大运行内存 + */ + public int getMemoryLimit() { + return memoryLimit; + } + + /** + * 设置最大运行内存. + * + * @param memoryLimit + */ + public void setMemoryLimit(int memoryLimit) { + this.memoryLimit = memoryLimit; + } + + /** + * 获取试题描述. + * + * @return 试题描述 + */ + public String getDescription() { + return description; + } + + /** + * 设置试题描述. + * + * @param description - 试题描述 + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * 获取输入格式描述. + * + * @return 输入格式描述 + */ + public String getInputFormat() { + return inputFormat; + } + + /** + * 设置输入格式描述. + * + * @param inputFormat - 输入格式描述 + */ + public void setInpuFormatt(String inputFormat) { + this.inputFormat = inputFormat; + } + + /** + * 获取输出格式描述. + * + * @return 输出格式描述 + */ + public String getOutputFormat() { + return outputFormat; + } + + /** + * 设置输出格式描述. + * + * @param outputFormat - 输出格式描述 + */ + public void setOutputFormat(String outputFormat) { + this.outputFormat = outputFormat; + } + + /** + * 获取样例输入. + * + * @return 样例输入 + */ + public String getSampleInput() { + return sampleInput; + } + + /** + * 设置样例输入. + * + * @param sampleInput - 样例输入 + */ + public void setSampleInput(String sampleInput) { + this.sampleInput = sampleInput; + } + + /** + * 获取样例输出. + * + * @return 样例输出 + */ + public String getSampleOutput() { + return sampleOutput; + } + + /** + * 设置样例输出. + * + * @param sampleOutput - 样例输出 + */ + public void setSampleOutput(String sampleOutput) { + this.sampleOutput = sampleOutput; + } + + /** + * 获取试题提示. + * + * @return 试题提示 + */ + public String getHint() { + return hint; + } + + /** + * 设置试题提示. + * + * @param hint - 试题提示 + */ + public void setHint(String hint) { + this.hint = hint; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return String.format( + "Problem: [ProblemID=%s, isPublic=%s, ProblemName=%s, TimeLimit=%s, " + + "MemoryLimit=%s, Description=%s, InputFormat=%s, OutputFormat=%s, " + + "SampleInput=%s, SampleOutput=%s, Hint=%s]", + new Object[] { + problemId, + isPublic, + problemName, + timeLimit, + memoryLimit, + description, + inputFormat, + outputFormat, + sampleInput, + sampleOutput, + hint + }); + } + + /** 试题的唯一标识符. */ + private long problemId; + + /** 试题是否公开. */ + private boolean isPublic; + + /** 试题名称. */ + private String problemName; + + /** 最大运行时间. */ + private int timeLimit; + + /** 最大运行内存. */ + private int memoryLimit; + + /** 试题描述. */ + private String description; + + /** 输入格式. */ + private String inputFormat; + + /** 输出格式. */ + private String outputFormat; + + /** 样例输入. */ + private String sampleInput; + + /** 样例输出. */ + private String sampleOutput; + + /** 试题提示. */ + private String hint; + + /** 唯一的序列化标识符. */ + private static final long serialVersionUID = 4703482016721365341L; } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/model/Submission.java b/judger/src/main/java/org/verwandlung/voj/judger/model/Submission.java index 3fd44b72..f627a6df 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/model/Submission.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/model/Submission.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -43,315 +43,334 @@ import java.util.Date; /** - * 评测记录的Model. - * 对应数据库中的voj_submissions数据表. - * + * 评测记录的Model. 对应数据库中的voj_submissions数据表. + * * @author Haozhe Xie */ public class Submission implements Serializable { - /** - * 评测记录类的默认构造函数. - */ - public Submission() { } - - /** - * 评测记录类的构造函数. - * @param submissionId - 评测记录的唯一标识符 - * @param problem - 评测对应的试题对象 - * @param uid - 评测提交者的用户的唯一标识符 - * @param language - 提交所使用的语言对象 - * @param submitTime - 评测提交时间 - * @param executeTime - 评测开始执行时间 - * @param usedTime - 评测运行总时间 - * @param usedMemory - 评测运行占用最大内存 - * @param judgeResultSlug - 评测结果的唯一标识符 - * @param judgeScore - 评测运行得分 - * @param judgeLog - 评测运行日志 - * @param code - 评测所执行的代码 - */ - public Submission(long submissionId, Problem problem, long uid, Language language, Date submitTime, - Date executeTime, int usedTime, int usedMemory, String judgeResultSlug, int judgeScore, - String judgeLog, String code) { - this.submissionId = submissionId; - this.problem = problem; - this.uid = uid; - this.language = language; - this.submitTime = submitTime; - this.executeTime = executeTime; - this.usedTime = usedTime; - this.usedMemory = usedMemory; - this.judgeResultSlug = judgeResultSlug; - this.judgeScore = judgeScore; - this.judgeLog = judgeLog; - this.code = code; - } - - /** - * 获取评测记录的唯一标识符. - * @return 评测记录的唯一标识符 - */ - public long getSubmissionId() { - return submissionId; - } - - /** - * 设置评测记录的唯一标识符. - * @param submissionId - 评测记录的唯一标识符. - */ - public void setSubmissionId(long submissionId) { - this.submissionId = submissionId; - } - - /** - * 获取评测对应的试题对象. - * @return 试题对象 - */ - public Problem getProblem() { - return problem; - } - - /** - * 设置评测对应的试题对象. - * @param problem - 试题对象 - */ - public void setProblem(Problem problem) { - this.problem = problem; - } - - /** - * 获取评测提交者的用户唯一标识符. - * @return 用户的唯一标识符 - */ - public long getUid() { - return uid; - } - - /** - * 设置评测提交者的用户唯一标识符. - * @param uid - 用户唯一标识符 - */ - public void setUid(long uid) { - this.uid = uid; - } - - /** - * 获取提交所使用的语言对象. - * @return 提交所使用的语言对象 - */ - public Language getLanguage() { - return language; - } - - /** - * 设置提交所使用的语言对象. - * @param language - 提交所使用的语言对象 - */ - public void setLanguage(Language language) { - this.language = language; - } - - /** - * 获取评测提交时间. - * @return 评测提交时间 - */ - public Date getSubmitTime() { - return submitTime; - } - - /** - * 设置评测提交时间. - * @param submitTime - 评测提交时间 - */ - public void setSubmitTime(Date submitTime) { - this.submitTime = submitTime; - } - - /** - * 获取评测开始执行时间. - * @return 评测开始执行时间 - */ - public Date getExecuteTime() { - return executeTime; - } - - /** - * 设置评测开始执行时间. - * @param executeTime - 评测开始执行时间 - */ - public void setExecuteTime(Date executeTime) { - this.executeTime = executeTime; - } - - /** - * 获取评测运行总时间. - * @return 评测运行总时间 - */ - public int getUsedTime() { - return usedTime; - } - - /** - * 设置评测运行总时间. - * @param usedTime - 评测运行总时间 - */ - public void setUsedTime(int usedTime) { - this.usedTime = usedTime; - } - - /** - * 获取评测运行占用最大内存. - * @return 评测运行占用最大内存 - */ - public int getUsedMemory() { - return usedMemory; - } - - /** - * 设置评测运行占用最大内存. - * @param usedMemory - 评测运行占用最大内存 - */ - public void setUsedMemory(int usedMemory) { - this.usedMemory = usedMemory; - } - - /** - * 获取评测结果的唯一英文缩写. - * @return 评测结果的唯一英文缩写 - */ - public String getJudgeResultSlug() { - return judgeResultSlug; - } - - /** - * 设置评测结果. - * @param judgeResultSlug - 评测结果的唯一英文缩写 - */ - public void setJudgeResultSlug(String judgeResultSlug) { - this.judgeResultSlug = judgeResultSlug; - } - - /** - * 获取评测运行得分. - * @return 评测运行得分 - */ - public int getJudgeScore() { - return judgeScore; - } - - /** - * 设置评测运行得分. - * @param judgeScore - 评测运行得分 - */ - public void setJudgeScore(int judgeScore) { - this.judgeScore = judgeScore; - } - - /** - * 获取评测运行日志. - * @return 评测运行日志 - */ - public String getJudgeLog() { - return judgeLog; - } - - /** - * 设置评测运行日志 - * @param judgeLog - 评测运行日志 - */ - public void setJudgeLog(String judgeLog) { - this.judgeLog = judgeLog; - } - - /** - * 设置评测所执行的代码. - * @return 评测所执行的代码 - */ - public String getCode() { - return code; - } - - /** - * 设置评测所执行的代码. - * @param code - 评测所执行的代码 - */ - public void setCode(String code) { - this.code = code; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return String.format("Submission [ID=%d, Problem={%s}, Uid={%s}, Language={%s}, SubmitTime={%s}, " - + "ExecuteTime={%s}, UsedTime=%d, UsedMemory=%d, JudgeResultSlug={%s}, JudgeScore=%d, " - + "JudgeLog=%s, Code=%s]", - new Object[] { submissionId, problem, uid, language, submitTime, executeTime, usedTime, usedMemory, - judgeResultSlug, judgeScore, judgeLog, code}); - } - - /** - * 评测记录的唯一标识符. - */ - private long submissionId; - - /** - * 评测对应的试题对象. - */ - private Problem problem; - - /** - * 评测提交者用户的唯一标识符. - */ - private long uid; - - /** - * 提交所使用的语言对象. - */ - private Language language; - - /** - * 评测提交时间. - */ - private Date submitTime; - - /** - * 评测开始执行时间. - */ - private Date executeTime; - - /** - * 评测运行总时间. - */ - private int usedTime; - - /** - * 评测运行占用最大内存. - */ - private int usedMemory; - - /** - * 评测结果. - */ - private String judgeResultSlug; - - /** - * 评测运行得分. - */ - private int judgeScore; - - /** - * 评测运行日志. - */ - private String judgeLog; - - /** - * 评测所执行的代码. - */ - private String code; - - /** - * 唯一的序列化标识符. - */ - private static final long serialVersionUID = -6017296127470986766L; + /** 评测记录类的默认构造函数. */ + public Submission() {} + + /** + * 评测记录类的构造函数. + * + * @param submissionId - 评测记录的唯一标识符 + * @param problem - 评测对应的试题对象 + * @param uid - 评测提交者的用户的唯一标识符 + * @param language - 提交所使用的语言对象 + * @param submitTime - 评测提交时间 + * @param executeTime - 评测开始执行时间 + * @param usedTime - 评测运行总时间 + * @param usedMemory - 评测运行占用最大内存 + * @param judgeResultSlug - 评测结果的唯一标识符 + * @param judgeScore - 评测运行得分 + * @param judgeLog - 评测运行日志 + * @param code - 评测所执行的代码 + */ + public Submission( + long submissionId, + Problem problem, + long uid, + Language language, + Date submitTime, + Date executeTime, + int usedTime, + int usedMemory, + String judgeResultSlug, + int judgeScore, + String judgeLog, + String code) { + this.submissionId = submissionId; + this.problem = problem; + this.uid = uid; + this.language = language; + this.submitTime = submitTime; + this.executeTime = executeTime; + this.usedTime = usedTime; + this.usedMemory = usedMemory; + this.judgeResultSlug = judgeResultSlug; + this.judgeScore = judgeScore; + this.judgeLog = judgeLog; + this.code = code; + } + + /** + * 获取评测记录的唯一标识符. + * + * @return 评测记录的唯一标识符 + */ + public long getSubmissionId() { + return submissionId; + } + + /** + * 设置评测记录的唯一标识符. + * + * @param submissionId - 评测记录的唯一标识符. + */ + public void setSubmissionId(long submissionId) { + this.submissionId = submissionId; + } + + /** + * 获取评测对应的试题对象. + * + * @return 试题对象 + */ + public Problem getProblem() { + return problem; + } + + /** + * 设置评测对应的试题对象. + * + * @param problem - 试题对象 + */ + public void setProblem(Problem problem) { + this.problem = problem; + } + + /** + * 获取评测提交者的用户唯一标识符. + * + * @return 用户的唯一标识符 + */ + public long getUid() { + return uid; + } + + /** + * 设置评测提交者的用户唯一标识符. + * + * @param uid - 用户唯一标识符 + */ + public void setUid(long uid) { + this.uid = uid; + } + + /** + * 获取提交所使用的语言对象. + * + * @return 提交所使用的语言对象 + */ + public Language getLanguage() { + return language; + } + + /** + * 设置提交所使用的语言对象. + * + * @param language - 提交所使用的语言对象 + */ + public void setLanguage(Language language) { + this.language = language; + } + + /** + * 获取评测提交时间. + * + * @return 评测提交时间 + */ + public Date getSubmitTime() { + return submitTime; + } + + /** + * 设置评测提交时间. + * + * @param submitTime - 评测提交时间 + */ + public void setSubmitTime(Date submitTime) { + this.submitTime = submitTime; + } + + /** + * 获取评测开始执行时间. + * + * @return 评测开始执行时间 + */ + public Date getExecuteTime() { + return executeTime; + } + + /** + * 设置评测开始执行时间. + * + * @param executeTime - 评测开始执行时间 + */ + public void setExecuteTime(Date executeTime) { + this.executeTime = executeTime; + } + + /** + * 获取评测运行总时间. + * + * @return 评测运行总时间 + */ + public int getUsedTime() { + return usedTime; + } + + /** + * 设置评测运行总时间. + * + * @param usedTime - 评测运行总时间 + */ + public void setUsedTime(int usedTime) { + this.usedTime = usedTime; + } + + /** + * 获取评测运行占用最大内存. + * + * @return 评测运行占用最大内存 + */ + public int getUsedMemory() { + return usedMemory; + } + + /** + * 设置评测运行占用最大内存. + * + * @param usedMemory - 评测运行占用最大内存 + */ + public void setUsedMemory(int usedMemory) { + this.usedMemory = usedMemory; + } + + /** + * 获取评测结果的唯一英文缩写. + * + * @return 评测结果的唯一英文缩写 + */ + public String getJudgeResultSlug() { + return judgeResultSlug; + } + + /** + * 设置评测结果. + * + * @param judgeResultSlug - 评测结果的唯一英文缩写 + */ + public void setJudgeResultSlug(String judgeResultSlug) { + this.judgeResultSlug = judgeResultSlug; + } + + /** + * 获取评测运行得分. + * + * @return 评测运行得分 + */ + public int getJudgeScore() { + return judgeScore; + } + + /** + * 设置评测运行得分. + * + * @param judgeScore - 评测运行得分 + */ + public void setJudgeScore(int judgeScore) { + this.judgeScore = judgeScore; + } + + /** + * 获取评测运行日志. + * + * @return 评测运行日志 + */ + public String getJudgeLog() { + return judgeLog; + } + + /** + * 设置评测运行日志 + * + * @param judgeLog - 评测运行日志 + */ + public void setJudgeLog(String judgeLog) { + this.judgeLog = judgeLog; + } + + /** + * 设置评测所执行的代码. + * + * @return 评测所执行的代码 + */ + public String getCode() { + return code; + } + + /** + * 设置评测所执行的代码. + * + * @param code - 评测所执行的代码 + */ + public void setCode(String code) { + this.code = code; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return String.format( + "Submission [ID=%d, Problem={%s}, Uid={%s}, Language={%s}, SubmitTime={%s}, " + + "ExecuteTime={%s}, UsedTime=%d, UsedMemory=%d, JudgeResultSlug={%s}, JudgeScore=%d, " + + "JudgeLog=%s, Code=%s]", + new Object[] { + submissionId, + problem, + uid, + language, + submitTime, + executeTime, + usedTime, + usedMemory, + judgeResultSlug, + judgeScore, + judgeLog, + code + }); + } + + /** 评测记录的唯一标识符. */ + private long submissionId; + + /** 评测对应的试题对象. */ + private Problem problem; + + /** 评测提交者用户的唯一标识符. */ + private long uid; + + /** 提交所使用的语言对象. */ + private Language language; + + /** 评测提交时间. */ + private Date submitTime; + + /** 评测开始执行时间. */ + private Date executeTime; + + /** 评测运行总时间. */ + private int usedTime; + + /** 评测运行占用最大内存. */ + private int usedMemory; + + /** 评测结果. */ + private String judgeResultSlug; + + /** 评测运行得分. */ + private int judgeScore; + + /** 评测运行日志. */ + private String judgeLog; + + /** 评测所执行的代码. */ + private String code; + + /** 唯一的序列化标识符. */ + private static final long serialVersionUID = -6017296127470986766L; } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/model/User.java b/judger/src/main/java/org/verwandlung/voj/judger/model/User.java index 39fdd567..2ca2280e 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/model/User.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/model/User.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -42,185 +42,192 @@ import java.io.Serializable; /** - * 用户的Model. - * 对应数据库中的voj_users数据表. - * + * 用户的Model. 对应数据库中的voj_users数据表. + * * @author Haozhe Xie */ public class User implements Serializable { - /** - * 用户的默认构造函数. - */ - public User() { } - - /** - * 用户的构造函数. - * @param username - 用户名 - * @param password - 密码 - * @param email - 电子邮件地址 - * @param userGroup - 用户组 - * @param preferLanguage - 用户偏好语言 - */ - public User(String username, String password, String email, - UserGroup userGroup, Language preferLanguage) { - this.username = username; - this.password = password; - this.email = email; - this.userGroup = userGroup; - this.preferLanguage = preferLanguage; - } - - /** - * User类的构造函数. - * @param uid - 用户唯一标识符 - * @param username - 用户名 - * @param password - 密码 - * @param email - 电子邮件地址 - * @param userGroup - 用户组 - * @param preferLanguage - 用户偏好语言 - */ - public User(int uid, String username, String password, String email, - UserGroup userGroup, Language preferLanguage) { - this(username, password, email, userGroup, preferLanguage); - this.uid = uid; - } - - /** - * 获取用户唯一标识符. - * @return 用户唯一标识符 - */ - public long getUid() { - return uid; - } - - /** - * 设置用户唯一标识符. - * @param uid - 用户唯一标识符 - */ - public void setUid(long uid) { - this.uid = uid; - } - - /** - * 获取用户名. - * @return 用户名 - */ - public String getUsername() { - return username; - } - - /** - * 设置用户名. - * @param username - 用户名 - */ - public void setUsername(String username) { - this.username = username; - } - - /** - * 获取密码(已采用MD5加密). - * @return 密码 - */ - public String getPassword() { - return password; - } - - /** - * 设置密码. - * @param password - 密码 - */ - public void setPassword(String password) { - this.password = password; - } - - /** - * 获取电子邮件地址. - * @return 电子邮件地址 - */ - public String getEmail() { - return email; - } - - /** - * 设置电子邮件地址 - * @param email - 电子邮件地址 - */ - public void setEmail(String email) { - this.email = email; - } - - /** - * 获取用户组. - * @return 用户组对象 - */ - public UserGroup getUserGroup() { - return userGroup; - } - - /** - * 设置用户组. - * @param userGroup - 用户组对象 - */ - public void setUserGroup(UserGroup userGroup) { - this.userGroup = userGroup; - } - - /** - * 获取用户偏好语言对象. - * @return 用户偏好语言对象 - */ - public Language getPreferLanguage() { - return preferLanguage; - } - - /** - * 设置用户偏好语言对象 - * @param preferLanguage - 用户偏好语言对象 - */ - public void setPreferLanguage(Language preferLanguage) { - this.preferLanguage = preferLanguage; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - public String toString() { - return String.format("User: [Uid=%s, Username=%s, Password=%s, Email=%s, UserGroup={%s}, Language={%s}]", - new Object[] { uid, username, password, email, userGroup, preferLanguage }); - } - - /** - * 用户的唯一标识符. - */ - private long uid; - - /** - * 用户名. - */ - private String username; - - /** - * 密码(已采用MD5加密). - */ - private String password; - - /** - * 电子邮件地址. - */ - private String email; - - /** - * 用户组对象. - */ - private UserGroup userGroup; - - /** - * 用户偏好语言对象. - */ - private Language preferLanguage; - - /** - * 唯一的序列化标识符. - */ - private static final long serialVersionUID = 2264535351943252507L; + /** 用户的默认构造函数. */ + public User() {} + + /** + * 用户的构造函数. + * + * @param username - 用户名 + * @param password - 密码 + * @param email - 电子邮件地址 + * @param userGroup - 用户组 + * @param preferLanguage - 用户偏好语言 + */ + public User( + String username, + String password, + String email, + UserGroup userGroup, + Language preferLanguage) { + this.username = username; + this.password = password; + this.email = email; + this.userGroup = userGroup; + this.preferLanguage = preferLanguage; + } + + /** + * User类的构造函数. + * + * @param uid - 用户唯一标识符 + * @param username - 用户名 + * @param password - 密码 + * @param email - 电子邮件地址 + * @param userGroup - 用户组 + * @param preferLanguage - 用户偏好语言 + */ + public User( + int uid, + String username, + String password, + String email, + UserGroup userGroup, + Language preferLanguage) { + this(username, password, email, userGroup, preferLanguage); + this.uid = uid; + } + + /** + * 获取用户唯一标识符. + * + * @return 用户唯一标识符 + */ + public long getUid() { + return uid; + } + + /** + * 设置用户唯一标识符. + * + * @param uid - 用户唯一标识符 + */ + public void setUid(long uid) { + this.uid = uid; + } + + /** + * 获取用户名. + * + * @return 用户名 + */ + public String getUsername() { + return username; + } + + /** + * 设置用户名. + * + * @param username - 用户名 + */ + public void setUsername(String username) { + this.username = username; + } + + /** + * 获取密码(已采用MD5加密). + * + * @return 密码 + */ + public String getPassword() { + return password; + } + + /** + * 设置密码. + * + * @param password - 密码 + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * 获取电子邮件地址. + * + * @return 电子邮件地址 + */ + public String getEmail() { + return email; + } + + /** + * 设置电子邮件地址 + * + * @param email - 电子邮件地址 + */ + public void setEmail(String email) { + this.email = email; + } + + /** + * 获取用户组. + * + * @return 用户组对象 + */ + public UserGroup getUserGroup() { + return userGroup; + } + + /** + * 设置用户组. + * + * @param userGroup - 用户组对象 + */ + public void setUserGroup(UserGroup userGroup) { + this.userGroup = userGroup; + } + + /** + * 获取用户偏好语言对象. + * + * @return 用户偏好语言对象 + */ + public Language getPreferLanguage() { + return preferLanguage; + } + + /** + * 设置用户偏好语言对象 + * + * @param preferLanguage - 用户偏好语言对象 + */ + public void setPreferLanguage(Language preferLanguage) { + this.preferLanguage = preferLanguage; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + public String toString() { + return String.format( + "User: [Uid=%s, Username=%s, Password=%s, Email=%s, UserGroup={%s}, Language={%s}]", + new Object[] {uid, username, password, email, userGroup, preferLanguage}); + } + + /** 用户的唯一标识符. */ + private long uid; + + /** 用户名. */ + private String username; + + /** 密码(已采用MD5加密). */ + private String password; + + /** 电子邮件地址. */ + private String email; + + /** 用户组对象. */ + private UserGroup userGroup; + + /** 用户偏好语言对象. */ + private Language preferLanguage; + + /** 唯一的序列化标识符. */ + private static final long serialVersionUID = 2264535351943252507L; } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/model/UserGroup.java b/judger/src/main/java/org/verwandlung/voj/judger/model/UserGroup.java index 2b14631f..b939fd6a 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/model/UserGroup.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/model/UserGroup.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -42,103 +42,100 @@ import java.io.Serializable; /** - * 用户组的Model. - * 对应数据库中的voj_user_groups数据表. - * + * 用户组的Model. 对应数据库中的voj_user_groups数据表. + * * @author Haozhe Xie */ public class UserGroup implements Serializable { - /** - * 用户组的默认构造函数. - */ - public UserGroup() { } - - /** - * 用户组的构造函数. - * @param userGroupId - 用户组的唯一标识符 - * @param userGroupSlug - 用户组的唯一英文简称 - * @param userGroupName - 用户组名称 - */ - public UserGroup(int userGroupId, String userGroupSlug, String userGroupName) { - this.userGroupId = userGroupId; - this.userGroupSlug = userGroupSlug; - this.userGroupName = userGroupName; - } - - /** - * 获取用户组唯一标识符. - * @return 用户组唯一标识符 - */ - public int getUserGroupId() { - return userGroupId; - } + /** 用户组的默认构造函数. */ + public UserGroup() {} + + /** + * 用户组的构造函数. + * + * @param userGroupId - 用户组的唯一标识符 + * @param userGroupSlug - 用户组的唯一英文简称 + * @param userGroupName - 用户组名称 + */ + public UserGroup(int userGroupId, String userGroupSlug, String userGroupName) { + this.userGroupId = userGroupId; + this.userGroupSlug = userGroupSlug; + this.userGroupName = userGroupName; + } + + /** + * 获取用户组唯一标识符. + * + * @return 用户组唯一标识符 + */ + public int getUserGroupId() { + return userGroupId; + } + + /** + * 设置用户组唯一标识符. + * + * @param userGroupId - 用户组唯一标识符 + */ + public void setUserGroupId(int userGroupId) { + this.userGroupId = userGroupId; + } - /** - * 设置用户组唯一标识符. - * @param userGroupId - 用户组唯一标识符 - */ - public void setUserGroupId(int userGroupId) { - this.userGroupId = userGroupId; - } + /** + * 获取用户组唯一英文简称. + * + * @return 用户组唯一英文简称 + */ + public String getUserGroupSlug() { + return userGroupSlug; + } - /** - * 获取用户组唯一英文简称. - * @return 用户组唯一英文简称 - */ - public String getUserGroupSlug() { - return userGroupSlug; - } + /** + * 设置用户组唯一英文简称. + * + * @param userGroupSlug - 用户组唯一英文简称 + */ + public void setUserGroupSlug(String userGroupSlug) { + this.userGroupSlug = userGroupSlug; + } - /** - * 设置用户组唯一英文简称. - * @param userGroupSlug - 用户组唯一英文简称 - */ - public void setUserGroupSlug(String userGroupSlug) { - this.userGroupSlug = userGroupSlug; - } + /** + * 获取用户组名称. + * + * @return 用户组名称 + */ + public String getUserGroupName() { + return userGroupName; + } - /** - * 获取用户组名称. - * @return 用户组名称 - */ - public String getUserGroupName() { - return userGroupName; - } + /** + * 设置用户组名称. + * + * @param userGroupName - 用户组名称 + */ + public void setUserGroupName(String userGroupName) { + this.userGroupName = userGroupName; + } - /** - * 设置用户组名称. - * @param userGroupName - 用户组名称 - */ - public void setUserGroupName(String userGroupName) { - this.userGroupName = userGroupName; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return String.format("UserGroup [ID=%d, Slug=%s, Name=%s]", - new Object[] { userGroupId, userGroupSlug, userGroupName }); - } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return String.format( + "UserGroup [ID=%d, Slug=%s, Name=%s]", + new Object[] {userGroupId, userGroupSlug, userGroupName}); + } - /** - * 用户组唯一标识符. - */ - private int userGroupId; + /** 用户组唯一标识符. */ + private int userGroupId; - /** - * 用户组唯一英文简称. - */ - private String userGroupSlug; + /** 用户组唯一英文简称. */ + private String userGroupSlug; - /** - * 用户组名称. - */ - private String userGroupName; + /** 用户组名称. */ + private String userGroupName; - /** - * 唯一的序列化标识符. - */ - private static final long serialVersionUID = -4267702283058634035L; + /** 唯一的序列化标识符. */ + private static final long serialVersionUID = -4267702283058634035L; } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/util/DigestUtils.java b/judger/src/main/java/org/verwandlung/voj/judger/util/DigestUtils.java index b0e021dc..d111aa53 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/util/DigestUtils.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/util/DigestUtils.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -45,80 +45,84 @@ /** * 生成随机字符串类. + * * @author Haozhe Xie */ public class DigestUtils { - /** - * Utility classes should not have a public constructor. - */ - private DigestUtils() { } - - /** - * 生成GUID. - * @return GUID - */ - public static String getGuid() { - return UUID.randomUUID().toString(); - } - - /** - * 获取MD5加密后的密码. - * @param password - 未经MD5加密的密码 - * @return MD5加密后的密码 - */ - public static String md5Hex(String password) { - String md5 = ""; - if ( password == null || password.isEmpty() ) { - return ""; - } - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - md.update(password.getBytes()); - byte byteData[] = md.digest(); - - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < byteData.length; i++) { - sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1)); - } - md5 = sb.toString(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - return md5; - } - - /** - * 生成随机字符串. - * @param length - 字符串长度 - * @param mode - 字符串生成模式 - * @return 随机字符串 - */ - public static String getRandomString(int length, Mode mode) { - StringBuffer buffer = new StringBuffer(); - String characters = ""; + /** Utility classes should not have a public constructor. */ + private DigestUtils() {} + + /** + * 生成GUID. + * + * @return GUID + */ + public static String getGuid() { + return UUID.randomUUID().toString(); + } + + /** + * 获取MD5加密后的密码. + * + * @param password - 未经MD5加密的密码 + * @return MD5加密后的密码 + */ + public static String md5Hex(String password) { + String md5 = ""; + if (password == null || password.isEmpty()) { + return ""; + } + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(password.getBytes()); + byte byteData[] = md.digest(); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < byteData.length; i++) { + sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1)); + } + md5 = sb.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return md5; + } + + /** + * 生成随机字符串. + * + * @param length - 字符串长度 + * @param mode - 字符串生成模式 + * @return 随机字符串 + */ + public static String getRandomString(int length, Mode mode) { + StringBuffer buffer = new StringBuffer(); + String characters = ""; + + switch (mode) { + case ALPHA: + characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + break; + case ALPHANUMERIC: + characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + break; + case NUMERIC: + characters = "1234567890"; + break; + } + + int charactersLength = characters.length(); + for (int i = 0; i < length; ++i) { + double index = Math.random() * charactersLength; + buffer.append(characters.charAt((int) index)); + } + return buffer.toString(); + } - switch(mode) { - case ALPHA: - characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - break; - case ALPHANUMERIC: - characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; - break; - case NUMERIC: - characters = "1234567890"; - break; - } - - int charactersLength = characters.length(); - for ( int i = 0; i < length; ++ i ) { - double index = Math.random() * charactersLength; - buffer.append(characters.charAt((int) index)); - } - return buffer.toString(); - } - - /** - * 字符串生成模式枚举类. - */ - public static enum Mode { ALPHA, ALPHANUMERIC, NUMERIC } + /** 字符串生成模式枚举类. */ + public static enum Mode { + ALPHA, + ALPHANUMERIC, + NUMERIC + } } diff --git a/judger/src/main/java/org/verwandlung/voj/judger/util/NativeLibraryLoader.java b/judger/src/main/java/org/verwandlung/voj/judger/util/NativeLibraryLoader.java index a3fdb339..4de3d681 100644 --- a/judger/src/main/java/org/verwandlung/voj/judger/util/NativeLibraryLoader.java +++ b/judger/src/main/java/org/verwandlung/voj/judger/util/NativeLibraryLoader.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -47,51 +47,50 @@ /** * Contains helper methods for loading native libraries, particularly JNI. - * + * * @author gkubisa */ public class NativeLibraryLoader { - /** - * Utility classes should not have a public constructor. - */ - private NativeLibraryLoader() { } - - /** - * Loads a native shared library. It tries the standard System.loadLibrary - * method first and if it fails, it looks for the library in the current - * class path. It will handle libraries packed within jar files, too. - * - * @param libraryName - name of the library to load - * @throws IOException if the library cannot be extracted from a jar file - * into a temporary file - */ - public static void loadLibrary(String libraryName) throws IOException { - try { - System.loadLibrary(libraryName); - } catch (UnsatisfiedLinkError e) { - String fileName = System.mapLibraryName(libraryName); + /** Utility classes should not have a public constructor. */ + private NativeLibraryLoader() {} + + /** + * Loads a native shared library. It tries the standard System.loadLibrary method first and if it + * fails, it looks for the library in the current class path. It will handle libraries packed + * within jar files, too. + * + * @param libraryName - name of the library to load + * @throws IOException if the library cannot be extracted from a jar file into a temporary file + */ + public static void loadLibrary(String libraryName) throws IOException { + try { + System.loadLibrary(libraryName); + } catch (UnsatisfiedLinkError e) { + String fileName = System.mapLibraryName(libraryName); + + int dotPosition = fileName.lastIndexOf('.'); + File file = + File.createTempFile(fileName.substring(0, dotPosition), fileName.substring(dotPosition)); + file.deleteOnExit(); + + byte[] buffer = new byte[4096]; + InputStream inputStream = + NativeLibraryLoader.class.getClassLoader().getResourceAsStream(fileName); + OutputStream outputStream = new FileOutputStream(file); + + try { + while (inputStream.available() > 0) { + int StreamLength = inputStream.read(buffer); + if (StreamLength >= 0) { + outputStream.write(buffer, 0, StreamLength); + } + } + } finally { + outputStream.close(); + inputStream.close(); + } - int dotPosition = fileName.lastIndexOf('.'); - File file = File.createTempFile(fileName.substring(0, dotPosition), fileName.substring(dotPosition)); - file.deleteOnExit(); - - byte[] buffer = new byte[4096]; - InputStream inputStream = NativeLibraryLoader.class.getClassLoader().getResourceAsStream(fileName); - OutputStream outputStream = new FileOutputStream(file); - - try { - while ( inputStream.available() > 0 ) { - int StreamLength = inputStream.read(buffer); - if ( StreamLength >= 0 ) { - outputStream.write(buffer, 0, StreamLength); - } - } - } finally { - outputStream.close(); - inputStream.close(); - } - - System.load(file.getAbsolutePath()); - } - } + System.load(file.getAbsolutePath()); + } + } } diff --git a/judger/src/test/java/org/verwandlung/voj/judger/core/ComparatorTest.java b/judger/src/test/java/org/verwandlung/voj/judger/core/ComparatorTest.java index a0ab1634..264e937d 100644 --- a/judger/src/test/java/org/verwandlung/voj/judger/core/ComparatorTest.java +++ b/judger/src/test/java/org/verwandlung/voj/judger/core/ComparatorTest.java @@ -15,31 +15,30 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * */ package org.verwandlung.voj.judger.core; -import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; @@ -62,116 +61,89 @@ */ @ExtendWith(SpringExtension.class) @Transactional -@ContextConfiguration({ "classpath:test-spring-context.xml" }) +@ContextConfiguration({"classpath:test-spring-context.xml"}) public class ComparatorTest { - /** - * 构建测试用例. - */ - @BeforeAll - public static void setUp() throws IOException { - FileOutputStream stdOutputStream = null; - FileOutputStream outputStream = null; - // Make Directory for TestCases - File checkpointsDirFile = new File("/tmp/voj-matcher-tests"); - if (!checkpointsDirFile.exists()) { - checkpointsDirFile.mkdirs(); - } - // TestCase: MatchExactly - stdOutputStream = new FileOutputStream(new File( - "/tmp/voj-matcher-tests/match-exactly-std.txt")); - outputStream = new FileOutputStream(new File( - "/tmp/voj-matcher-tests/match-exactly.txt")); - String matchExactlyString = "32768"; - IOUtils.write(matchExactlyString, stdOutputStream); - IOUtils.write(matchExactlyString, outputStream); - // TestCase: MatchWithSpaces - stdOutputStream = new FileOutputStream(new File( - "/tmp/voj-matcher-tests/match-with-spaces-std.txt")); - outputStream = new FileOutputStream(new File( - "/tmp/voj-matcher-tests/match-with-spaces.txt")); - String matchWithSpacesString = "Output Test with Spaces"; - IOUtils.write(matchWithSpacesString, stdOutputStream); - IOUtils.write(matchWithSpacesString + " \n \n", outputStream); - // TestCase: Mismatch - stdOutputStream = new FileOutputStream(new File( - "/tmp/voj-matcher-tests/mismatch-std.txt")); - outputStream = new FileOutputStream(new File( - "/tmp/voj-matcher-tests/mismatch.txt")); - String mismatchString1 = "45652 \n\n"; - String mismatchString2 = "24334"; - IOUtils.write(mismatchString1, stdOutputStream); - IOUtils.write(mismatchString2, outputStream); - // TestCase: MismatchEmptyString - outputStream = new FileOutputStream(new File( - "/tmp/voj-matcher-tests/mismatch-empty.txt")); - String mismatchString3 = "\n"; - IOUtils.write(mismatchString3, outputStream); - } + /** 构建测试用例. */ + @BeforeAll + public static void setUp() throws IOException { + FileOutputStream stdOutputStream = null; + FileOutputStream outputStream = null; + // Make Directory for TestCases + File checkpointsDirFile = new File("/tmp/voj-matcher-tests"); + if (!checkpointsDirFile.exists()) { + checkpointsDirFile.mkdirs(); + } + // TestCase: MatchExactly + stdOutputStream = + new FileOutputStream(new File("/tmp/voj-matcher-tests/match-exactly-std.txt")); + outputStream = new FileOutputStream(new File("/tmp/voj-matcher-tests/match-exactly.txt")); + String matchExactlyString = "32768"; + IOUtils.write(matchExactlyString, stdOutputStream); + IOUtils.write(matchExactlyString, outputStream); + // TestCase: MatchWithSpaces + stdOutputStream = + new FileOutputStream(new File("/tmp/voj-matcher-tests/match-with-spaces-std.txt")); + outputStream = new FileOutputStream(new File("/tmp/voj-matcher-tests/match-with-spaces.txt")); + String matchWithSpacesString = "Output Test with Spaces"; + IOUtils.write(matchWithSpacesString, stdOutputStream); + IOUtils.write(matchWithSpacesString + " \n \n", outputStream); + // TestCase: Mismatch + stdOutputStream = new FileOutputStream(new File("/tmp/voj-matcher-tests/mismatch-std.txt")); + outputStream = new FileOutputStream(new File("/tmp/voj-matcher-tests/mismatch.txt")); + String mismatchString1 = "45652 \n\n"; + String mismatchString2 = "24334"; + IOUtils.write(mismatchString1, stdOutputStream); + IOUtils.write(mismatchString2, outputStream); + // TestCase: MismatchEmptyString + outputStream = new FileOutputStream(new File("/tmp/voj-matcher-tests/mismatch-empty.txt")); + String mismatchString3 = "\n"; + IOUtils.write(mismatchString3, outputStream); + } - /** - * 清除测试用例. - */ - @AfterAll - public static void tearDown() { - File checkpointsDirFile = new File("/tmp/voj-matcher-tests"); - if (checkpointsDirFile.exists()) { - checkpointsDirFile.delete(); - } - } + /** 清除测试用例. */ + @AfterAll + public static void tearDown() { + File checkpointsDirFile = new File("/tmp/voj-matcher-tests"); + if (checkpointsDirFile.exists()) { + checkpointsDirFile.delete(); + } + } - /** - * 测试用例: 测试isOutputTheSame(String, String)方法 - * 测试数据: 输入和输出完全相同 - * 测试结果: 返回true, 表示输出结果正确 - */ - @Test - public void testMatchExactly() throws IOException { - String standardOutputFilePath = "/tmp/voj-matcher-tests/match-exactly-std.txt"; - String outputFilePath = "/tmp/voj-matcher-tests/match-exactly.txt"; - Assertions.assertTrue(comparator.isOutputTheSame(standardOutputFilePath, outputFilePath)); - } + /** 测试用例: 测试isOutputTheSame(String, String)方法 测试数据: 输入和输出完全相同 测试结果: 返回true, 表示输出结果正确 */ + @Test + public void testMatchExactly() throws IOException { + String standardOutputFilePath = "/tmp/voj-matcher-tests/match-exactly-std.txt"; + String outputFilePath = "/tmp/voj-matcher-tests/match-exactly.txt"; + Assertions.assertTrue(comparator.isOutputTheSame(standardOutputFilePath, outputFilePath)); + } - /** - * 测试用例: 测试isOutputTheSame(String, String)方法 - * 测试数据: 输入和输出基本相同, 在行尾存在多余的空白字符 - * 测试结果: 返回true, 表示输出结果正确 - */ - @Test - public void testMatchWithSpaces() throws IOException { - String standardOutputFilePath = "/tmp/voj-matcher-tests/match-with-spaces-std.txt"; - String outputFilePath = "/tmp/voj-matcher-tests/match-with-spaces.txt"; - Assertions.assertTrue(comparator.isOutputTheSame(standardOutputFilePath, - outputFilePath)); - Assertions.assertTrue(comparator.isOutputTheSame(outputFilePath, standardOutputFilePath)); - } + /** + * 测试用例: 测试isOutputTheSame(String, String)方法 测试数据: 输入和输出基本相同, 在行尾存在多余的空白字符 测试结果: 返回true, 表示输出结果正确 + */ + @Test + public void testMatchWithSpaces() throws IOException { + String standardOutputFilePath = "/tmp/voj-matcher-tests/match-with-spaces-std.txt"; + String outputFilePath = "/tmp/voj-matcher-tests/match-with-spaces.txt"; + Assertions.assertTrue(comparator.isOutputTheSame(standardOutputFilePath, outputFilePath)); + Assertions.assertTrue(comparator.isOutputTheSame(outputFilePath, standardOutputFilePath)); + } - /** - * 测试用例: 测试isOutputTheSame(String, String)方法 - * 测试数据: 输入和输出不完全相同 - * 测试结果: 返回false, 表示输出结果不正确 - */ - @Test - public void testMismatch() throws IOException { - String standardOutputFilePath = "/tmp/voj-matcher-tests/mismatch-std.txt"; - String outputFilePath = "/tmp/voj-matcher-tests/mismatch.txt"; - Assertions.assertFalse(comparator.isOutputTheSame(standardOutputFilePath, outputFilePath)); - } + /** 测试用例: 测试isOutputTheSame(String, String)方法 测试数据: 输入和输出不完全相同 测试结果: 返回false, 表示输出结果不正确 */ + @Test + public void testMismatch() throws IOException { + String standardOutputFilePath = "/tmp/voj-matcher-tests/mismatch-std.txt"; + String outputFilePath = "/tmp/voj-matcher-tests/mismatch.txt"; + Assertions.assertFalse(comparator.isOutputTheSame(standardOutputFilePath, outputFilePath)); + } - /** - * 测试用例: 测试isOutputTheSame(String, String)方法 - * 测试数据: 输入和输出不完全相同 - * 测试结果: 返回false, 表示输出结果不正确 - */ - @Test - public void testMismatchEmptyString() throws IOException { - String standardOutputFilePath = "/tmp/voj-matcher-tests/mismatch-std.txt"; - String outputFilePath = "/tmp/voj-matcher-tests/mismatch-empty.txt"; - Assertions.assertFalse(comparator.isOutputTheSame(standardOutputFilePath, outputFilePath)); - } + /** 测试用例: 测试isOutputTheSame(String, String)方法 测试数据: 输入和输出不完全相同 测试结果: 返回false, 表示输出结果不正确 */ + @Test + public void testMismatchEmptyString() throws IOException { + String standardOutputFilePath = "/tmp/voj-matcher-tests/mismatch-std.txt"; + String outputFilePath = "/tmp/voj-matcher-tests/mismatch-empty.txt"; + Assertions.assertFalse(comparator.isOutputTheSame(standardOutputFilePath, outputFilePath)); + } - /** - * 待测试的Matcher对象. - */ - @Autowired - private Comparator comparator; + /** 待测试的Matcher对象. */ + @Autowired private Comparator comparator; } diff --git a/judger/src/test/java/org/verwandlung/voj/judger/core/CompilerTest.java b/judger/src/test/java/org/verwandlung/voj/judger/core/CompilerTest.java index d4382604..7b8be0ec 100644 --- a/judger/src/test/java/org/verwandlung/voj/judger/core/CompilerTest.java +++ b/judger/src/test/java/org/verwandlung/voj/judger/core/CompilerTest.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -55,85 +55,59 @@ /** * 程序编译器的测试类. - * + * * @author Haozhe Xie */ @ExtendWith(SpringExtension.class) @Transactional @ContextConfiguration({"classpath:test-spring-context.xml"}) public class CompilerTest { - /** - * 测试用例: 测试getCompileResult()方法 - * 测试数据: 使用可以编译通过的C++代码 - * 预期结果: 编译通过 - */ - @Test - public void testGetCompileResultCppWithSuccess() throws Exception { - String workDirectory = workBaseDirectory + "/voj-1000"; - String baseFileName = "random-name"; - Submission submission = submissionMapper.getSubmission(1000); - preprocessor.createTestCode(submission, workDirectory, baseFileName); - - Map result = compiler.getCompileResult(submission, workDirectory, baseFileName); - Assertions.assertEquals(true, result.get("isSuccessful")); - } - - /** - * 测试用例: 测试getCompileResult()方法 - * 测试数据: 使用可以编译通过的Java代码 - * 预期结果: 编译通过 - */ - @Test - public void testGetCompileResultJavaWithSuccess() throws Exception { - String workDirectory = workBaseDirectory + "/voj-1001"; - String baseFileName = "RandomName"; - Submission submission = submissionMapper.getSubmission(1001); - preprocessor.createTestCode(submission, workDirectory, baseFileName); - - Map result = compiler.getCompileResult(submission, workDirectory, baseFileName); - Assertions.assertEquals(true, result.get("isSuccessful")); - } - - /** - * 测试用例: 测试getCompileResult()方法 - * 测试数据: 使用可以无法编译通过的C++代码 - * 预期结果: 编译失败 - */ - @Test - public void testGetCompileResultCppWithError() throws Exception { - String workDirectory = workBaseDirectory + "/voj-1002"; - String baseFileName = "random-name"; - Submission submission = submissionMapper.getSubmission(1002); - preprocessor.createTestCode(submission, workDirectory, baseFileName); - - Map result = compiler.getCompileResult(submission, workDirectory, baseFileName); - Assertions.assertEquals(false, result.get("isSuccessful")); - } - - /** - * 待测试的Compiler对象. - */ - @Autowired - private Compiler compiler; - - /** - * 自动注入的Preprocessor对象. - * 用于构建测试用例. - */ - @Autowired - private Preprocessor preprocessor; - - /** - * 自动注入的SubmissionMapper对象. - * 用于构建测试用例. - */ - @Autowired - private SubmissionMapper submissionMapper; - - /** - * 评测机的工作目录. - * 用于存储编译结果以及程序输出结果. - */ - @Value("${judger.workDir}") - private String workBaseDirectory; + /** 测试用例: 测试getCompileResult()方法 测试数据: 使用可以编译通过的C++代码 预期结果: 编译通过 */ + @Test + public void testGetCompileResultCppWithSuccess() throws Exception { + String workDirectory = workBaseDirectory + "/voj-1000"; + String baseFileName = "random-name"; + Submission submission = submissionMapper.getSubmission(1000); + preprocessor.createTestCode(submission, workDirectory, baseFileName); + + Map result = compiler.getCompileResult(submission, workDirectory, baseFileName); + Assertions.assertEquals(true, result.get("isSuccessful")); + } + + /** 测试用例: 测试getCompileResult()方法 测试数据: 使用可以编译通过的Java代码 预期结果: 编译通过 */ + @Test + public void testGetCompileResultJavaWithSuccess() throws Exception { + String workDirectory = workBaseDirectory + "/voj-1001"; + String baseFileName = "RandomName"; + Submission submission = submissionMapper.getSubmission(1001); + preprocessor.createTestCode(submission, workDirectory, baseFileName); + + Map result = compiler.getCompileResult(submission, workDirectory, baseFileName); + Assertions.assertEquals(true, result.get("isSuccessful")); + } + + /** 测试用例: 测试getCompileResult()方法 测试数据: 使用可以无法编译通过的C++代码 预期结果: 编译失败 */ + @Test + public void testGetCompileResultCppWithError() throws Exception { + String workDirectory = workBaseDirectory + "/voj-1002"; + String baseFileName = "random-name"; + Submission submission = submissionMapper.getSubmission(1002); + preprocessor.createTestCode(submission, workDirectory, baseFileName); + + Map result = compiler.getCompileResult(submission, workDirectory, baseFileName); + Assertions.assertEquals(false, result.get("isSuccessful")); + } + + /** 待测试的Compiler对象. */ + @Autowired private Compiler compiler; + + /** 自动注入的Preprocessor对象. 用于构建测试用例. */ + @Autowired private Preprocessor preprocessor; + + /** 自动注入的SubmissionMapper对象. 用于构建测试用例. */ + @Autowired private SubmissionMapper submissionMapper; + + /** 评测机的工作目录. 用于存储编译结果以及程序输出结果. */ + @Value("${judger.workDir}") + private String workBaseDirectory; } diff --git a/judger/src/test/java/org/verwandlung/voj/judger/core/PreprocessorTest.java b/judger/src/test/java/org/verwandlung/voj/judger/core/PreprocessorTest.java index c8a775cd..c41e664b 100644 --- a/judger/src/test/java/org/verwandlung/voj/judger/core/PreprocessorTest.java +++ b/judger/src/test/java/org/verwandlung/voj/judger/core/PreprocessorTest.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -55,61 +55,54 @@ /** * 预处理器的测试类. - * + * * @author Haozhe Xie */ @ExtendWith(SpringExtension.class) @Transactional @ContextConfiguration({"classpath:test-spring-context.xml"}) public class PreprocessorTest { - /** - * 测试用例: 测试createTestCode(Submission, String, String)方法 - * 测试数据: 使用存在的提交记录(Submission#1000) - * 预期结果: 在指定位置创建源代码文件 - * @throws Exception - */ - @Test - public void testCreateTestCodeCpp() throws Exception { - Submission submission = submissionMapper.getSubmission(1000); - String workDirectory = "/tmp/voj-1000/"; - String baseFileName = "random-name"; - - preprocessor.createTestCode(submission, workDirectory, baseFileName); - FileInputStream inputStream = new FileInputStream("/tmp/voj-1000/random-name.cpp"); - String code = IOUtils.toString(inputStream); - inputStream.close(); - Assertions.assertEquals(submission.getCode(), code); - } - - /** - * 测试用例: 测试createTestCode(Submission, String, String)方法 - * 测试数据: 使用存在的提交记录(Submission#1001) - * 预期结果: 在指定位置创建源代码文件 - * @throws Exception - */ - @Test - public void testCreateTestCodeJava() throws Exception { - Submission submission = submissionMapper.getSubmission(1001); - String workDirectory = "/tmp/voj-1001/"; - String baseFileName = "RandomName"; - - preprocessor.createTestCode(submission, workDirectory, baseFileName); - FileInputStream inputStream = new FileInputStream("/tmp/voj-1001/RandomName.java"); - String code = IOUtils.toString(inputStream).replace("RandomName", "Main"); - inputStream.close(); - Assertions.assertEquals(submission.getCode(), code); - } - - /** - * 待测试的Preprocessor对象. - */ - @Autowired - private Preprocessor preprocessor; - - /** - * 自动注入的SubmissionMapper对象. - * 用于构造测试用例. - */ - @Autowired - private SubmissionMapper submissionMapper; + /** + * 测试用例: 测试createTestCode(Submission, String, String)方法 测试数据: 使用存在的提交记录(Submission#1000) 预期结果: + * 在指定位置创建源代码文件 + * + * @throws Exception + */ + @Test + public void testCreateTestCodeCpp() throws Exception { + Submission submission = submissionMapper.getSubmission(1000); + String workDirectory = "/tmp/voj-1000/"; + String baseFileName = "random-name"; + + preprocessor.createTestCode(submission, workDirectory, baseFileName); + FileInputStream inputStream = new FileInputStream("/tmp/voj-1000/random-name.cpp"); + String code = IOUtils.toString(inputStream); + inputStream.close(); + Assertions.assertEquals(submission.getCode(), code); + } + + /** + * 测试用例: 测试createTestCode(Submission, String, String)方法 测试数据: 使用存在的提交记录(Submission#1001) 预期结果: + * 在指定位置创建源代码文件 + * + * @throws Exception + */ + @Test + public void testCreateTestCodeJava() throws Exception { + Submission submission = submissionMapper.getSubmission(1001); + String workDirectory = "/tmp/voj-1001/"; + String baseFileName = "RandomName"; + + preprocessor.createTestCode(submission, workDirectory, baseFileName); + FileInputStream inputStream = new FileInputStream("/tmp/voj-1001/RandomName.java"); + String code = IOUtils.toString(inputStream).replace("RandomName", "Main"); + inputStream.close(); + Assertions.assertEquals(submission.getCode(), code); + } + + /** 待测试的Preprocessor对象. */ + @Autowired private Preprocessor preprocessor; + + /** 自动注入的SubmissionMapper对象. 用于构造测试用例. */ + @Autowired private SubmissionMapper submissionMapper; } diff --git a/judger/src/test/java/org/verwandlung/voj/judger/core/RunnerTest.java b/judger/src/test/java/org/verwandlung/voj/judger/core/RunnerTest.java index bf671db9..c12d2d9e 100644 --- a/judger/src/test/java/org/verwandlung/voj/judger/core/RunnerTest.java +++ b/judger/src/test/java/org/verwandlung/voj/judger/core/RunnerTest.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -55,91 +55,73 @@ /** * 程序执行器的测试类. - * + * * @author Haozhe Xie */ @ExtendWith(SpringExtension.class) @Transactional @ContextConfiguration({"classpath:test-spring-context.xml"}) public class RunnerTest { - /** - * 测试用例: 测试getRuntimeResult(Submission, int, String, String, String, String)方法 - * 测试数据: 使用可以编译通过的C++代码 - * 预期结果: 编译成功并运行产生输出 - */ - @Test - public void testGetRuntimeResultCpp() throws Exception { - String workDirectory = workBaseDirectory + "/voj-1000"; - String baseFileName = "random-name"; - Submission submission = submissionMapper.getSubmission(1000); - - String inputFilePath = workBaseDirectory + "/testpoints/1000/input#0.txt"; - String outputFilePath = workBaseDirectory + "/voj-1000/output#0.txt"; - - preprocessor.createTestCode(submission, workDirectory, baseFileName); - preprocessor.fetchTestPoints(submission.getProblem().getProblemId()); - compiler.getCompileResult(submission, workDirectory, baseFileName); - - Map result = - runner.getRuntimeResult(submission, workDirectory, baseFileName, inputFilePath, outputFilePath); - Assertions.assertEquals("AC", result.get("runtimeResult")); - } - - /** - * 测试用例: 测试getRuntimeResult(Submission, int, String, String, String, String)方法 - * 测试数据: 使用可以编译通过的Java代码 - * 预期结果: 编译成功并运行产生输出 - * - * The test case is disabled for passing CI on AppVeyor. - */ - public void testGetRuntimeResultJava() throws Exception { - String workDirectory = workBaseDirectory + "/voj-1001"; - String baseFileName = "RandomName"; - Submission submission = submissionMapper.getSubmission(1001); - - String inputFilePath = workBaseDirectory + "/testpoints/1001/input#0.txt"; - String outputFilePath = workBaseDirectory + "/voj-1000/output#0.txt"; - - preprocessor.createTestCode(submission, workDirectory, baseFileName); - preprocessor.fetchTestPoints(submission.getProblem().getProblemId()); - compiler.getCompileResult(submission, workDirectory, baseFileName); - - Map result = - runner.getRuntimeResult(submission, workDirectory, baseFileName, inputFilePath, outputFilePath); - Assertions.assertEquals("AC", result.get("runtimeResult")); - } - - /** - * 待测试的Runner对象. - */ - @Autowired - private Runner runner; - - /** - * 自动注入的Compiler对象. - * 用于构建测试用例. - */ - @Autowired - private Compiler compiler; - - /** - * 自动注入的Preprocessor对象. - * 用于构建测试用例. - */ - @Autowired - private Preprocessor preprocessor; - - /** - * 自动注入的SubmissionMapper对象. - * 用于构建测试用例. - */ - @Autowired - private SubmissionMapper submissionMapper; - - /** - * 评测机的工作目录. - * 用于存储编译结果以及程序输出结果. - */ - @Value("${judger.workDir}") - private String workBaseDirectory; + /** + * 测试用例: 测试getRuntimeResult(Submission, int, String, String, String, String)方法 测试数据: + * 使用可以编译通过的C++代码 预期结果: 编译成功并运行产生输出 + */ + @Test + public void testGetRuntimeResultCpp() throws Exception { + String workDirectory = workBaseDirectory + "/voj-1000"; + String baseFileName = "random-name"; + Submission submission = submissionMapper.getSubmission(1000); + + String inputFilePath = workBaseDirectory + "/testpoints/1000/input#0.txt"; + String outputFilePath = workBaseDirectory + "/voj-1000/output#0.txt"; + + preprocessor.createTestCode(submission, workDirectory, baseFileName); + preprocessor.fetchTestPoints(submission.getProblem().getProblemId()); + compiler.getCompileResult(submission, workDirectory, baseFileName); + + Map result = + runner.getRuntimeResult( + submission, workDirectory, baseFileName, inputFilePath, outputFilePath); + Assertions.assertEquals("AC", result.get("runtimeResult")); + } + + /** + * 测试用例: 测试getRuntimeResult(Submission, int, String, String, String, String)方法 测试数据: + * 使用可以编译通过的Java代码 预期结果: 编译成功并运行产生输出 + * + *

The test case is disabled for passing CI on AppVeyor. + */ + public void testGetRuntimeResultJava() throws Exception { + String workDirectory = workBaseDirectory + "/voj-1001"; + String baseFileName = "RandomName"; + Submission submission = submissionMapper.getSubmission(1001); + + String inputFilePath = workBaseDirectory + "/testpoints/1001/input#0.txt"; + String outputFilePath = workBaseDirectory + "/voj-1000/output#0.txt"; + + preprocessor.createTestCode(submission, workDirectory, baseFileName); + preprocessor.fetchTestPoints(submission.getProblem().getProblemId()); + compiler.getCompileResult(submission, workDirectory, baseFileName); + + Map result = + runner.getRuntimeResult( + submission, workDirectory, baseFileName, inputFilePath, outputFilePath); + Assertions.assertEquals("AC", result.get("runtimeResult")); + } + + /** 待测试的Runner对象. */ + @Autowired private Runner runner; + + /** 自动注入的Compiler对象. 用于构建测试用例. */ + @Autowired private Compiler compiler; + + /** 自动注入的Preprocessor对象. 用于构建测试用例. */ + @Autowired private Preprocessor preprocessor; + + /** 自动注入的SubmissionMapper对象. 用于构建测试用例. */ + @Autowired private SubmissionMapper submissionMapper; + + /** 评测机的工作目录. 用于存储编译结果以及程序输出结果. */ + @Value("${judger.workDir}") + private String workBaseDirectory; } diff --git a/judger/src/test/java/org/verwandlung/voj/judger/mapper/CheckpointMapperTest.java b/judger/src/test/java/org/verwandlung/voj/judger/mapper/CheckpointMapperTest.java index 7dcd2850..66427066 100644 --- a/judger/src/test/java/org/verwandlung/voj/judger/mapper/CheckpointMapperTest.java +++ b/judger/src/test/java/org/verwandlung/voj/judger/mapper/CheckpointMapperTest.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -53,42 +53,33 @@ /** * CheckpointMapper测试类. - * + * * @author Haozhe Xie */ @ExtendWith(SpringExtension.class) @Transactional @ContextConfiguration({"classpath:test-spring-context.xml"}) public class CheckpointMapperTest { - /** - * 测试用例: 测试getCheckpointsUsingProblemId(long)方法 - * 测试数据: 使用存在的试题唯一标识符(1000) - * 预期结果: 返回对应的测试点列表(10个项目) - */ - @Test - public void testGetCheckpointsUsingProblemIdExists() { - List checkpoints = checkpointMapper.getCheckpointsUsingProblemId(1000); - Assertions.assertEquals(10, checkpoints.size()); - - Checkpoint firstCheckpoint = checkpoints.get(0); - String output = firstCheckpoint.getOutput(); - Assertions.assertEquals("45652\r\n", output); - } - - /** - * 测试用例: 测试getCheckpointsUsingProblemId(long)方法 - * 测试数据: 使用不存在的试题唯一标识符(0) - * 预期结果: 返回对应的测试点列表(0个项目) - */ - @Test - public void testGetCheckpointsUsingProblemIdNotExists() { - List checkpoints = checkpointMapper.getCheckpointsUsingProblemId(0); - Assertions.assertEquals(0, checkpoints.size()); - } - - /** - * 待测试的CheckpointMapper对象. - */ - @Autowired - private CheckpointMapper checkpointMapper; + /** + * 测试用例: 测试getCheckpointsUsingProblemId(long)方法 测试数据: 使用存在的试题唯一标识符(1000) 预期结果: 返回对应的测试点列表(10个项目) + */ + @Test + public void testGetCheckpointsUsingProblemIdExists() { + List checkpoints = checkpointMapper.getCheckpointsUsingProblemId(1000); + Assertions.assertEquals(10, checkpoints.size()); + + Checkpoint firstCheckpoint = checkpoints.get(0); + String output = firstCheckpoint.getOutput(); + Assertions.assertEquals("45652\r\n", output); + } + + /** 测试用例: 测试getCheckpointsUsingProblemId(long)方法 测试数据: 使用不存在的试题唯一标识符(0) 预期结果: 返回对应的测试点列表(0个项目) */ + @Test + public void testGetCheckpointsUsingProblemIdNotExists() { + List checkpoints = checkpointMapper.getCheckpointsUsingProblemId(0); + Assertions.assertEquals(0, checkpoints.size()); + } + + /** 待测试的CheckpointMapper对象. */ + @Autowired private CheckpointMapper checkpointMapper; } diff --git a/judger/src/test/java/org/verwandlung/voj/judger/mapper/JudgeResultMapperTest.java b/judger/src/test/java/org/verwandlung/voj/judger/mapper/JudgeResultMapperTest.java index c4c093aa..3d227b68 100644 --- a/judger/src/test/java/org/verwandlung/voj/judger/mapper/JudgeResultMapperTest.java +++ b/judger/src/test/java/org/verwandlung/voj/judger/mapper/JudgeResultMapperTest.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -51,40 +51,33 @@ /** * JudgeResultMapper测试类. + * * @author Haozhe Xie */ @ExtendWith(SpringExtension.class) @Transactional @ContextConfiguration({"classpath:test-spring-context.xml"}) public class JudgeResultMapperTest { - /** - * 测试用例: 测试getJudgeResultUsingSlug(String)方法 - * 测试数据: 普通评测结果(JudgeResult)的评测结果组唯一英文缩写 - * 预期结果: 返回评测结果(JudgeResult)的评测结果组对象 - */ - @Test - public void testGetJudgeResultUsingSlugExists() { - JudgeResult judgeResult = judgeResultMapper.getJudgeResultUsingSlug("AC"); - Assertions.assertNotNull(judgeResult); - - int judgeResultId = judgeResult.getJudgeResultId(); - Assertions.assertEquals(2, judgeResultId); - } - - /** - * 测试用例: 测试getJudgeResultUsingSlug(String)方法 - * 测试数据: 不存在的评测结果组唯一英文缩写 - * 预期结果: 返回空引用 - */ - @Test - public void testGetJudgeResultUsingSlugNotExists() { - JudgeResult judgeResult = judgeResultMapper.getJudgeResultUsingSlug("Not-Exists"); - Assertions.assertNull(judgeResult); - } - - /** - * 待测试的JudgeResultMapper对象. - */ - @Autowired - private JudgeResultMapper judgeResultMapper; + /** + * 测试用例: 测试getJudgeResultUsingSlug(String)方法 测试数据: 普通评测结果(JudgeResult)的评测结果组唯一英文缩写 预期结果: + * 返回评测结果(JudgeResult)的评测结果组对象 + */ + @Test + public void testGetJudgeResultUsingSlugExists() { + JudgeResult judgeResult = judgeResultMapper.getJudgeResultUsingSlug("AC"); + Assertions.assertNotNull(judgeResult); + + int judgeResultId = judgeResult.getJudgeResultId(); + Assertions.assertEquals(2, judgeResultId); + } + + /** 测试用例: 测试getJudgeResultUsingSlug(String)方法 测试数据: 不存在的评测结果组唯一英文缩写 预期结果: 返回空引用 */ + @Test + public void testGetJudgeResultUsingSlugNotExists() { + JudgeResult judgeResult = judgeResultMapper.getJudgeResultUsingSlug("Not-Exists"); + Assertions.assertNull(judgeResult); + } + + /** 待测试的JudgeResultMapper对象. */ + @Autowired private JudgeResultMapper judgeResultMapper; } diff --git a/judger/src/test/java/org/verwandlung/voj/judger/mapper/LanguageMapperTest.java b/judger/src/test/java/org/verwandlung/voj/judger/mapper/LanguageMapperTest.java index f37941a4..16f113e0 100644 --- a/judger/src/test/java/org/verwandlung/voj/judger/mapper/LanguageMapperTest.java +++ b/judger/src/test/java/org/verwandlung/voj/judger/mapper/LanguageMapperTest.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -53,83 +53,60 @@ /** * LanguageMapper测试类. - * + * * @author Haozhe Xie */ @ExtendWith(SpringExtension.class) @Transactional @ContextConfiguration({"classpath:test-spring-context.xml"}) public class LanguageMapperTest { - /** - * 测试用例: 测试getLanguageUsingId(int)方法 - * 测试数据: C语言的编程语言唯一标识符 - * 预期结果: 返回C语言的编程语言对象 - */ - @Test - public void testGetLanguageUsingIdExists() { - Language language = languageMapper.getLanguageUsingId(1); - Assertions.assertNotNull(language); - - String languageName = language.getLanguageName(); - Assertions.assertEquals("C", languageName); - } - - /** - * 测试用例: 测试getLanguageUsingId(int)方法 - * 测试数据: 不存在的编程语言唯一标识符 - * 预期结果: 返回空引用 - */ - @Test - public void testGetLanguageUsingIdNotExists() { - Language language = languageMapper.getLanguageUsingId(0); - Assertions.assertNull(language); - } - - /** - * 测试用例: 测试getLanguageUsingSlug(String)方法 - * 测试数据: C语言的编程语言唯一英文缩写 - * 预期结果: 返回C语言的编程语言对象 - */ - @Test - public void testGetLanguageUsingSlugExists() { - Language language = languageMapper.getLanguageUsingSlug("text/x-csrc"); - Assertions.assertNotNull(language); - - String languageName = language.getLanguageName(); - Assertions.assertEquals("C", languageName); - } - - /** - * 测试用例: 测试getLanguageUsingSlug(String)方法 - * 测试数据: 不存在的编程语言唯一英文缩写 - * 预期结果: 返回空引用 - */ - @Test - public void testGetLanguageUsingSlugNotExists() { - Language language = languageMapper.getLanguageUsingSlug("Not-Exists"); - Assertions.assertNull(language); - } + /** 测试用例: 测试getLanguageUsingId(int)方法 测试数据: C语言的编程语言唯一标识符 预期结果: 返回C语言的编程语言对象 */ + @Test + public void testGetLanguageUsingIdExists() { + Language language = languageMapper.getLanguageUsingId(1); + Assertions.assertNotNull(language); + + String languageName = language.getLanguageName(); + Assertions.assertEquals("C", languageName); + } + + /** 测试用例: 测试getLanguageUsingId(int)方法 测试数据: 不存在的编程语言唯一标识符 预期结果: 返回空引用 */ + @Test + public void testGetLanguageUsingIdNotExists() { + Language language = languageMapper.getLanguageUsingId(0); + Assertions.assertNull(language); + } + + /** 测试用例: 测试getLanguageUsingSlug(String)方法 测试数据: C语言的编程语言唯一英文缩写 预期结果: 返回C语言的编程语言对象 */ + @Test + public void testGetLanguageUsingSlugExists() { + Language language = languageMapper.getLanguageUsingSlug("text/x-csrc"); + Assertions.assertNotNull(language); + + String languageName = language.getLanguageName(); + Assertions.assertEquals("C", languageName); + } + + /** 测试用例: 测试getLanguageUsingSlug(String)方法 测试数据: 不存在的编程语言唯一英文缩写 预期结果: 返回空引用 */ + @Test + public void testGetLanguageUsingSlugNotExists() { + Language language = languageMapper.getLanguageUsingSlug("Not-Exists"); + Assertions.assertNull(language); + } + + /** 测试用例: 测试getAllLanguages()方法 测试数据: N/a 预期结果: 返回全部的编程语言列表(共6种语言) */ + @Test + public void testGetAllLanguages() { + List languages = languageMapper.getAllLanguages(); + Assertions.assertNotNull(languages); + Assertions.assertEquals(6, languages.size()); + + Language firstLanguage = languages.get(0); + Assertions.assertNotNull(firstLanguage); - /** - * 测试用例: 测试getAllLanguages()方法 - * 测试数据: N/a - * 预期结果: 返回全部的编程语言列表(共6种语言) - */ - @Test - public void testGetAllLanguages() { - List languages = languageMapper.getAllLanguages(); - Assertions.assertNotNull(languages); - Assertions.assertEquals(6, languages.size()); - - Language firstLanguage = languages.get(0); - Assertions.assertNotNull(firstLanguage); - - String languageName = firstLanguage.getLanguageName(); - Assertions.assertEquals("C", languageName); - } - /** - * 待测试的LanguageMapper对象. - */ - @Autowired - private LanguageMapper languageMapper; + String languageName = firstLanguage.getLanguageName(); + Assertions.assertEquals("C", languageName); + } + /** 待测试的LanguageMapper对象. */ + @Autowired private LanguageMapper languageMapper; } diff --git a/judger/src/test/java/org/verwandlung/voj/judger/mapper/ProblemMapperTest.java b/judger/src/test/java/org/verwandlung/voj/judger/mapper/ProblemMapperTest.java index edf3abf6..67065e40 100644 --- a/judger/src/test/java/org/verwandlung/voj/judger/mapper/ProblemMapperTest.java +++ b/judger/src/test/java/org/verwandlung/voj/judger/mapper/ProblemMapperTest.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -51,40 +51,30 @@ /** * ProblemMapper测试类. + * * @author Haozhe Xie */ @ExtendWith(SpringExtension.class) @Transactional @ContextConfiguration({"classpath:test-spring-context.xml"}) public class ProblemMapperTest { - /** - * 测试用例: 测试getProblem()方法 - * 测试数据: 使用A+B Problem的试题唯一标识符 - * 预期结果: 返回预期的试题对象 - */ - @Test - public void testGetProblemExists() { - Problem problem = problemMapper.getProblem(1000); - Assertions.assertNotNull(problem); - - String problemName = problem.getProblemName(); - Assertions.assertEquals("A+B Problem", problemName); - } - - /** - * 测试用例: 测试getProblem()方法 - * 测试数据: 使用不存在的试题唯一标识符 - * 预期结果: 返回空引用 - */ - @Test - public void testGetProblemNotExists() { - Problem problem = problemMapper.getProblem(0); - Assertions.assertNull(problem); - } - - /** - * 待测试的ProblemMapper对象. - */ - @Autowired - private ProblemMapper problemMapper; + /** 测试用例: 测试getProblem()方法 测试数据: 使用A+B Problem的试题唯一标识符 预期结果: 返回预期的试题对象 */ + @Test + public void testGetProblemExists() { + Problem problem = problemMapper.getProblem(1000); + Assertions.assertNotNull(problem); + + String problemName = problem.getProblemName(); + Assertions.assertEquals("A+B Problem", problemName); + } + + /** 测试用例: 测试getProblem()方法 测试数据: 使用不存在的试题唯一标识符 预期结果: 返回空引用 */ + @Test + public void testGetProblemNotExists() { + Problem problem = problemMapper.getProblem(0); + Assertions.assertNull(problem); + } + + /** 待测试的ProblemMapper对象. */ + @Autowired private ProblemMapper problemMapper; } diff --git a/judger/src/test/java/org/verwandlung/voj/judger/mapper/SubmissionMapperTest.java b/judger/src/test/java/org/verwandlung/voj/judger/mapper/SubmissionMapperTest.java index 3ba053dd..532f72e3 100644 --- a/judger/src/test/java/org/verwandlung/voj/judger/mapper/SubmissionMapperTest.java +++ b/judger/src/test/java/org/verwandlung/voj/judger/mapper/SubmissionMapperTest.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -51,40 +51,30 @@ /** * SubmissionMapper测试类. + * * @author Haozhe Xie */ @ExtendWith(SpringExtension.class) @Transactional @ContextConfiguration({"classpath:test-spring-context.xml"}) public class SubmissionMapperTest { - /** - * 测试用例: 测试getSubmission(long)方法 - * 测试数据: Problem#1000的提交记录的唯一标识符 - * 预期结果: 返回预期的Submission对象 - */ - @Test - public void testGetSubmissionExists() { - Submission submission = submissionMapper.getSubmission(1000); - Assertions.assertNotNull(submission); - - long problemId = submission.getProblem().getProblemId(); - Assertions.assertEquals(1000, problemId); - } - - /** - * 测试用例: 测试getSubmission(long)方法 - * 测试数据: 不存在的的提交记录唯一标识符 - * 预期结果: 返回空引用 - */ - @Test - public void testGetSubmissionNotExists() { - Submission submission = submissionMapper.getSubmission(0); - Assertions.assertNull(submission); - } - - /** - * 待测试的SubmissionMapper对象. - */ - @Autowired - private SubmissionMapper submissionMapper; + /** 测试用例: 测试getSubmission(long)方法 测试数据: Problem#1000的提交记录的唯一标识符 预期结果: 返回预期的Submission对象 */ + @Test + public void testGetSubmissionExists() { + Submission submission = submissionMapper.getSubmission(1000); + Assertions.assertNotNull(submission); + + long problemId = submission.getProblem().getProblemId(); + Assertions.assertEquals(1000, problemId); + } + + /** 测试用例: 测试getSubmission(long)方法 测试数据: 不存在的的提交记录唯一标识符 预期结果: 返回空引用 */ + @Test + public void testGetSubmissionNotExists() { + Submission submission = submissionMapper.getSubmission(0); + Assertions.assertNull(submission); + } + + /** 待测试的SubmissionMapper对象. */ + @Autowired private SubmissionMapper submissionMapper; } diff --git a/judger/src/test/java/org/verwandlung/voj/judger/mapper/UserGroupMapperTest.java b/judger/src/test/java/org/verwandlung/voj/judger/mapper/UserGroupMapperTest.java index 267ea2ba..f0c5366b 100644 --- a/judger/src/test/java/org/verwandlung/voj/judger/mapper/UserGroupMapperTest.java +++ b/judger/src/test/java/org/verwandlung/voj/judger/mapper/UserGroupMapperTest.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -51,41 +51,30 @@ /** * UserGroupMapper测试类. - * + * * @author Haozhe Xie */ @ExtendWith(SpringExtension.class) @Transactional @ContextConfiguration({"classpath:test-spring-context.xml"}) public class UserGroupMapperTest { - /** - * 测试用例: 测试getUserGroupUsingId(int)方法 - * 测试数据: 普通用户(User)的用户组唯一标识符 - * 预期结果: 返回用户(User)的用户组对象 - */ - @Test - public void testGetUserGroupUsingIdExists() { - UserGroup userGroup = userGroupMapper.getUserGroupUsingId(1); - Assertions.assertNotNull(userGroup); - - String userGroupSlug = userGroup.getUserGroupSlug(); - Assertions.assertEquals("forbidden", userGroupSlug); - } - - /** - * 测试用例: 测试getUserGroupUsingId(int)方法 - * 测试数据: 不存在的用户组唯一标识符 - * 预期结果: 返回空引用 - */ - @Test - public void testGetUserGroupUsingIdNotExists() { - UserGroup userGroup = userGroupMapper.getUserGroupUsingId(0); - Assertions.assertNull(userGroup); - } - - /** - * 待测试的UserGroupMapper对象. - */ - @Autowired - private UserGroupMapper userGroupMapper; + /** 测试用例: 测试getUserGroupUsingId(int)方法 测试数据: 普通用户(User)的用户组唯一标识符 预期结果: 返回用户(User)的用户组对象 */ + @Test + public void testGetUserGroupUsingIdExists() { + UserGroup userGroup = userGroupMapper.getUserGroupUsingId(1); + Assertions.assertNotNull(userGroup); + + String userGroupSlug = userGroup.getUserGroupSlug(); + Assertions.assertEquals("forbidden", userGroupSlug); + } + + /** 测试用例: 测试getUserGroupUsingId(int)方法 测试数据: 不存在的用户组唯一标识符 预期结果: 返回空引用 */ + @Test + public void testGetUserGroupUsingIdNotExists() { + UserGroup userGroup = userGroupMapper.getUserGroupUsingId(0); + Assertions.assertNull(userGroup); + } + + /** 待测试的UserGroupMapper对象. */ + @Autowired private UserGroupMapper userGroupMapper; } diff --git a/judger/src/test/java/org/verwandlung/voj/judger/mapper/UserMapperTest.java b/judger/src/test/java/org/verwandlung/voj/judger/mapper/UserMapperTest.java index 394d4eb4..50093d5c 100644 --- a/judger/src/test/java/org/verwandlung/voj/judger/mapper/UserMapperTest.java +++ b/judger/src/test/java/org/verwandlung/voj/judger/mapper/UserMapperTest.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -51,41 +51,30 @@ /** * UserMapper测试类. - * + * * @author Haozhe Xie */ @ExtendWith(SpringExtension.class) @Transactional @ContextConfiguration({"classpath:test-spring-context.xml"}) public class UserMapperTest { - /** - * 测试用例: 测试getUserUsingUsername(String)方法 - * 测试数据: 使用用户名为zjhzxhz的用户 - * 预期结果: 返回预期的用户对象 - */ - @Test - public void testGetUserUsingUsernameExists() { - User user = userMapper.getUserUsingUsername("Zjhzxhz"); - Assertions.assertNotNull(user); - - long uid = user.getUid(); - Assertions.assertEquals(1000, uid); - } - - /** - * 测试用例: 测试getUserUsingUsername(String)方法 - * 测试数据: 使用不存在的用户名 - * 预期结果: 返回空引用 - */ - @Test - public void testGetUserUsingUsernameNotExists() { - User user = userMapper.getUserUsingUsername("Not-Exists"); - Assertions.assertNull(user); - } - - /** - * 待测试的UserMapper对象. - */ - @Autowired - private UserMapper userMapper; + /** 测试用例: 测试getUserUsingUsername(String)方法 测试数据: 使用用户名为zjhzxhz的用户 预期结果: 返回预期的用户对象 */ + @Test + public void testGetUserUsingUsernameExists() { + User user = userMapper.getUserUsingUsername("Zjhzxhz"); + Assertions.assertNotNull(user); + + long uid = user.getUid(); + Assertions.assertEquals(1000, uid); + } + + /** 测试用例: 测试getUserUsingUsername(String)方法 测试数据: 使用不存在的用户名 预期结果: 返回空引用 */ + @Test + public void testGetUserUsingUsernameNotExists() { + User user = userMapper.getUserUsingUsername("Not-Exists"); + Assertions.assertNull(user); + } + + /** 待测试的UserMapper对象. */ + @Autowired private UserMapper userMapper; } diff --git a/web/src/main/java/org/verwandlung/voj/web/aspect/InterceptorAspect.java b/web/src/main/java/org/verwandlung/voj/web/aspect/InterceptorAspect.java index 31d47c3b..e86e49a8 100644 --- a/web/src/main/java/org/verwandlung/voj/web/aspect/InterceptorAspect.java +++ b/web/src/main/java/org/verwandlung/voj/web/aspect/InterceptorAspect.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -57,131 +57,144 @@ import org.verwandlung.voj.web.service.UserService; /** - * 拦截器的切面. - * 用于完成系统的权限控制. - * + * 拦截器的切面. 用于完成系统的权限控制. + * * @author Haozhe Xie */ @Aspect public class InterceptorAspect { - /** - * 控制板视图的切面. - * 用于检查用户是否有权限加载控制板视图. - * @param proceedingJoinPoint - ProceedingJoinPoint对象 - * @param request - HttpServletRequest对象 - * @return 一个包含预期试图的ModelAndView对象 - * @throws Throwable - */ - @Around(value = "execution(* org.verwandlung.voj.web.controller.AccountsController.dashboardView(..)) && args(request, ..)") - public ModelAndView dashboardViewInterceptor(ProceedingJoinPoint proceedingJoinPoint, - HttpServletRequest request) throws Throwable { - ModelAndView view = null; - HttpSession session = request.getSession(); - - if ( !isAllowToAccess(session, new String[] { "users", "administrators" }) ) { - RedirectView redirectView = new RedirectView(request.getContextPath() + "/accounts/login"); - redirectView.setExposeModelAttributes(false); - return new ModelAndView(redirectView); - } - view = (ModelAndView) proceedingJoinPoint.proceed(); - return view; - } - - /** - * 控制板中异步操作请求的切面. - * 检查用户是否有权限执行该操作. - * @param proceedingJoinPoint - ProceedingJoinPoint对象 - * @param request - HttpServletRequest对象 - * @return 预期的操作结果(Map对象) - * @throws Throwable - */ - @Around(value = "execution(* org.verwandlung.voj.web.controller.AccountsController.*InDashboardAction(..)) && args(.., request)") - public Map dashboardActionInterceptor(ProceedingJoinPoint proceedingJoinPoint, - HttpServletRequest request) throws Throwable { - HttpSession session = request.getSession(); - - if ( !isAllowToAccess(session, new String[] { "users", "administrators" }) ) { - throw new ResourceNotFoundException(); - } - @SuppressWarnings("unchecked") - Map result = (Map) proceedingJoinPoint.proceed(); - return result; - } - - /** - * 系统管理控制器的切面. - * 用于检查用户是否有权限执行对应操作. - * @param proceedingJoinPoint - ProceedingJoinPoint对象 - * @param request - HttpServletRequest对象 - * @param request - HttpServletResponse对象 - * @return 一个包含预期试图的ModelAndView对象 - * @throws Throwable - */ - @Around(value = "execution(* org.verwandlung.voj.web.controller.AdministrationController.*View(..)) && args(.., request, response)") - public ModelAndView administrationViewInterceptor(ProceedingJoinPoint proceedingJoinPoint, - HttpServletRequest request, HttpServletResponse response) throws Throwable { - ModelAndView view = null; - HttpSession session = request.getSession(); - - if ( !isAllowToAccess(session, new String[] { "administrators" }) ) { - RedirectView redirectView = new RedirectView(request.getContextPath() + "/accounts/dashboard"); - redirectView.setExposeModelAttributes(false); - return new ModelAndView(redirectView); - } - view = (ModelAndView) proceedingJoinPoint.proceed(); - return view; - } - - /** - * 系统管理控制器的切面. - * 用于检查用户是否有权限执行对应操作. - * @param proceedingJoinPoint - ProceedingJoinPoint对象 - * @param request - HttpRequest对象 - * @return 一个包含预期结果的Map对象 - * @throws Throwable - */ - @SuppressWarnings("unchecked") - @Around(value = "execution(* org.verwandlung.voj.web.controller.AdministrationController.*Action(..)) && args(.., request)") - public Map AdministrationActionInterceptor(ProceedingJoinPoint proceedingJoinPoint, - HttpServletRequest request) throws Throwable { - Map result = null; - HttpSession session = request.getSession(); - - if ( !isAllowToAccess(session, new String[] { "administrators" }) ) { - return null; - } - result = (Map) proceedingJoinPoint.proceed(); - return result; - } - - /** - * 检查用户是否有权限执行该操作. - * @param session - HttpSession对象 - * @param expectedUserGroupSlugs - 允许执行该操作对应的用户组 - * @return 用户是否有权限执行该操作 - */ - private boolean isAllowToAccess(HttpSession session, String[] expectedUserGroupSlugs) { - Boolean isLoggedIn = (Boolean)session.getAttribute("isLoggedIn"); - if ( isLoggedIn == null || !isLoggedIn.booleanValue() ) { - return false; - } - - long uid = (Long)session.getAttribute("uid"); - User user = userService.getUserUsingUid(uid); - String userGroupSlug = user.getUserGroup().getUserGroupSlug(); - - for ( String expectedUserGroupSlug : expectedUserGroupSlugs ) { - if ( userGroupSlug.equals(expectedUserGroupSlug) ) { - return true; - } - } - return false; - } - - /** - * 自动注入的UserService对象. - * 用于查询用户所属的用户组. - */ - @Autowired - private UserService userService; + /** + * 控制板视图的切面. 用于检查用户是否有权限加载控制板视图. + * + * @param proceedingJoinPoint - ProceedingJoinPoint对象 + * @param request - HttpServletRequest对象 + * @return 一个包含预期试图的ModelAndView对象 + * @throws Throwable + */ + @Around( + value = + "execution(* org.verwandlung.voj.web.controller.AccountsController.dashboardView(..)) &&" + + " args(request, ..)") + public ModelAndView dashboardViewInterceptor( + ProceedingJoinPoint proceedingJoinPoint, HttpServletRequest request) throws Throwable { + ModelAndView view = null; + HttpSession session = request.getSession(); + + if (!isAllowToAccess(session, new String[] {"users", "administrators"})) { + RedirectView redirectView = new RedirectView(request.getContextPath() + "/accounts/login"); + redirectView.setExposeModelAttributes(false); + return new ModelAndView(redirectView); + } + view = (ModelAndView) proceedingJoinPoint.proceed(); + return view; + } + + /** + * 控制板中异步操作请求的切面. 检查用户是否有权限执行该操作. + * + * @param proceedingJoinPoint - ProceedingJoinPoint对象 + * @param request - HttpServletRequest对象 + * @return 预期的操作结果(Map对象) + * @throws Throwable + */ + @Around( + value = + "execution(*" + + " org.verwandlung.voj.web.controller.AccountsController.*InDashboardAction(..)) &&" + + " args(.., request)") + public Map dashboardActionInterceptor( + ProceedingJoinPoint proceedingJoinPoint, HttpServletRequest request) throws Throwable { + HttpSession session = request.getSession(); + + if (!isAllowToAccess(session, new String[] {"users", "administrators"})) { + throw new ResourceNotFoundException(); + } + @SuppressWarnings("unchecked") + Map result = (Map) proceedingJoinPoint.proceed(); + return result; + } + + /** + * 系统管理控制器的切面. 用于检查用户是否有权限执行对应操作. + * + * @param proceedingJoinPoint - ProceedingJoinPoint对象 + * @param request - HttpServletRequest对象 + * @param request - HttpServletResponse对象 + * @return 一个包含预期试图的ModelAndView对象 + * @throws Throwable + */ + @Around( + value = + "execution(* org.verwandlung.voj.web.controller.AdministrationController.*View(..)) &&" + + " args(.., request, response)") + public ModelAndView administrationViewInterceptor( + ProceedingJoinPoint proceedingJoinPoint, + HttpServletRequest request, + HttpServletResponse response) + throws Throwable { + ModelAndView view = null; + HttpSession session = request.getSession(); + + if (!isAllowToAccess(session, new String[] {"administrators"})) { + RedirectView redirectView = + new RedirectView(request.getContextPath() + "/accounts/dashboard"); + redirectView.setExposeModelAttributes(false); + return new ModelAndView(redirectView); + } + view = (ModelAndView) proceedingJoinPoint.proceed(); + return view; + } + + /** + * 系统管理控制器的切面. 用于检查用户是否有权限执行对应操作. + * + * @param proceedingJoinPoint - ProceedingJoinPoint对象 + * @param request - HttpRequest对象 + * @return 一个包含预期结果的Map对象 + * @throws Throwable + */ + @SuppressWarnings("unchecked") + @Around( + value = + "execution(* org.verwandlung.voj.web.controller.AdministrationController.*Action(..)) &&" + + " args(.., request)") + public Map AdministrationActionInterceptor( + ProceedingJoinPoint proceedingJoinPoint, HttpServletRequest request) throws Throwable { + Map result = null; + HttpSession session = request.getSession(); + + if (!isAllowToAccess(session, new String[] {"administrators"})) { + return null; + } + result = (Map) proceedingJoinPoint.proceed(); + return result; + } + + /** + * 检查用户是否有权限执行该操作. + * + * @param session - HttpSession对象 + * @param expectedUserGroupSlugs - 允许执行该操作对应的用户组 + * @return 用户是否有权限执行该操作 + */ + private boolean isAllowToAccess(HttpSession session, String[] expectedUserGroupSlugs) { + Boolean isLoggedIn = (Boolean) session.getAttribute("isLoggedIn"); + if (isLoggedIn == null || !isLoggedIn.booleanValue()) { + return false; + } + + long uid = (Long) session.getAttribute("uid"); + User user = userService.getUserUsingUid(uid); + String userGroupSlug = user.getUserGroup().getUserGroupSlug(); + + for (String expectedUserGroupSlug : expectedUserGroupSlugs) { + if (userGroupSlug.equals(expectedUserGroupSlug)) { + return true; + } + } + return false; + } + + /** 自动注入的UserService对象. 用于查询用户所属的用户组. */ + @Autowired private UserService userService; } diff --git a/web/src/main/java/org/verwandlung/voj/web/aspect/ViewAspect.java b/web/src/main/java/org/verwandlung/voj/web/aspect/ViewAspect.java index b4f2b228..28f30bf3 100644 --- a/web/src/main/java/org/verwandlung/voj/web/aspect/ViewAspect.java +++ b/web/src/main/java/org/verwandlung/voj/web/aspect/ViewAspect.java @@ -15,24 +15,24 @@ * along with this program. If not, see . * * - * _ooOoo_ - * o8888888o - * 88" . "88 - * (| -_- |) - * O\ = /O - * ____/`---'\____ - * .' \\| |// `. - * / \\||| : |||// \ - * / _||||| -:- |||||- \ - * | | \\\ - /// | | - * | \_| ''\---/'' | | - * \ .-\__ `-` ___/-. / - * ___`. .' /--.--\ `. . __ - * ."" '< `.___\_<|>_/___.' >'"". - * | | : `- \`.;`\ _ /`;.`/ - ` : | | - * \ \ `-. \_ __\ /__ _/ .-` / / - * ======`-.____`-.___\_____/___.-`____.-'====== - * `=---=' + * _ooOoo_ + * o8888888o + * 88" . "88 + * (| -_- |) + * O\ = /O + * ____/`---'\____ + * .' \\| |// `. + * / \\||| : |||// \ + * / _||||| -:- |||||- \ + * | | \\\ - /// | | + * | \_| ''\---/'' | | + * \ .-\__ `-` ___/-. / + * ___`. .' /--.--\ `. . __ + * ."" '< `.___\_<|>_/___.' >'"". + * | | : `- \`.;`\ _ /`;.`/ - ` : | | + * \ \ `-. \_ __\ /__ _/ .-` / / + * ======`-.____`-.___\_____/___.-`____.-'====== + * `=---=' * * HERE BE BUDDHA * @@ -62,134 +62,138 @@ import org.verwandlung.voj.web.util.LocaleUtils; /** - * 视图的切面类. - * 在加载页面前加载已登录用户的个人信息及答题情况. + * 视图的切面类. 在加载页面前加载已登录用户的个人信息及答题情况. + * * @author Haozhe Xie */ @Aspect public class ViewAspect { - /** - * 加载已登录用户的个人信息及答题情况. - * @param proceedingJoinPoint - ProceedingJoinPoint对象 - * @param request - HttpRequest对象 - * @param response - HttpResponse对象 - * @return 一个包含预期视图的ModelAndView对象 - * @throws Throwable - ResourceNotFound异常 - */ - @Around(value = "execution(* org.verwandlung.voj.web.controller.*.*View(..)) && args(.., request, response)") - public ModelAndView getUserProfile(ProceedingJoinPoint proceedingJoinPoint, - HttpServletRequest request, HttpServletResponse response) throws Throwable { - ModelAndView view = null; - HttpSession session = request.getSession(); - - view = (ModelAndView) proceedingJoinPoint.proceed(); - view.addAllObjects(getSystemOptions()); - view.addObject("language", getUserLanguage(request, response)); - - boolean isLoggedIn = isLoggedIn(session); - if ( isLoggedIn ) { - long userId = (Long)session.getAttribute("uid"); - User user = userService.getUserUsingUid(userId); - - view.addObject("isLogin", isLoggedIn) - .addObject("myProfile", user) - .addObject("mySubmissionStats", submissionService.getSubmissionStatsOfUser(userId)); - } - return view; - } - - /** - * 检查用户是否已经登录. - * @param session - HttpSession 对象 - * @return 用户是否已经登录 - */ - private boolean isLoggedIn(HttpSession session) { - Boolean isLoggedIn = (Boolean)session.getAttribute("isLoggedIn"); - if ( isLoggedIn == null || !isLoggedIn.booleanValue() ) { - return false; - } - return true; - } - - /** - * 加载系统定义的选项(Option). - * @return 包含系统定义选项的键值对列表 - */ - private Map getSystemOptions() { - List