diff --git a/backend/entity/src/submit.rs b/backend/entity/src/submit.rs index 991d516f..e135768a 100644 --- a/backend/entity/src/submit.rs +++ b/backend/entity/src/submit.rs @@ -25,6 +25,7 @@ pub struct Model { pub memory: Option, #[sea_orm(default_value = 0, indexed)] pub pass_case: i32, + pub status: u32, #[sea_orm(default_value = false)] pub accept: bool, #[sea_orm(default_value = 0, indexed)] diff --git a/backend/src/controller/submit.rs b/backend/src/controller/submit.rs index 26831b60..f3b4a9a4 100644 --- a/backend/src/controller/submit.rs +++ b/backend/src/controller/submit.rs @@ -1,18 +1,22 @@ -use std::{borrow::BorrowMut, sync::Arc}; +use std::sync::Arc; -use sea_orm::{ActiveModelTrait, ActiveValue, EntityTrait, IntoActiveModel, QueryOrder}; +use sea_orm::{ActiveModelTrait, ActiveValue, EntityTrait, QueryOrder}; use thiserror::Error; use tokio_stream::StreamExt; use crate::{ grpc::{ - backend::SubmitStatus, - judger::{JudgeRequest, TestIo}, + backend::{submit_status, JudgeResult as BackendResult, SubmitStatus}, + judger::{judge_response, JudgeRequest, JudgeResponse, JudgeResult, JudgerCode, TestIo}, }, init::{config::CONFIG, db::DB}, }; -use super::util::{pubsub::PubSub, router::*}; +use super::util::{ + code::Code, + pubsub::{PubGuard, PubSub}, + router::*, +}; use entity::*; type TonicStream = @@ -74,6 +78,28 @@ impl Submit { } } +impl From for SubmitStatus { + fn from(value: i32) -> Self { + SubmitStatus { + task: Some(submit_status::Task::Case(value)), + } + } +} + +impl From for SubmitStatus { + fn from(value: JudgeResult) -> Self { + SubmitStatus { + task: Some(submit_status::Task::Result(BackendResult { + code: Into::::into(value.status()) as i32, + accuracy: Some(value.accuracy), + time: Some(value.time), + memory: Some(value.memory), + })), + } + } +} + +#[derive(Clone)] pub struct SubmitController { router: Arc, pubsub: Arc, i32>>, @@ -87,7 +113,69 @@ impl SubmitController { pubsub: Arc::new(PubSub::new()), }) } - async fn submit(&self, submit: Submit) -> Result { + async fn stream( + ps_guard: PubGuard, i32>, + mut stream: tonic::Streaming, + mut model: submit::ActiveModel, + mut scores: Vec, + ) { + let mut result = 0; + let mut running_case = 0; + let mut time = 0; + let mut mem = 0; + let mut status = JudgerCode::Ac; + scores.reverse(); + while let Some(res) = stream.next().await { + if res.is_err() { + break; + } + let res = res.unwrap(); + if res.task.is_none() { + log::warn!("mismatch proto(judger)"); + continue; + } + let task = res.task.unwrap(); + match task { + judge_response::Task::Case(case) => { + if ps_guard.send(Ok(case.clone().into())).is_err() { + log::trace!("client disconnected"); + } + if case != (running_case + 1) { + log::warn!("mismatch proto(judger)"); + } + running_case += 1; + } + judge_response::Task::Result(case) => { + if let Some(score) = scores.pop() { + if ps_guard.send(Ok(case.clone().into())).is_err() { + log::trace!("client disconnected"); + } + if case.status() == JudgerCode::Ac { + result += score; + } else { + status = case.status(); + mem += case.memory; + time += case.time; + break; + } + } else { + log::warn!("mismatch proto(judger), too many cases"); + } + } + } + } + model.committed = ActiveValue::Set(true); + model.score = ActiveValue::Set(result); + model.status = ActiveValue::Set(Into::::into(status) as u32); + model.pass_case = ActiveValue::Set(running_case); + model.time = ActiveValue::Set(Some(time)); + model.memory = ActiveValue::Set(Some(mem)); + + if let Err(err) = model.update(DB.get().unwrap()).await { + log::warn!("failed to commit the judge result: {}", err); + } + } + pub async fn submit(&self, submit: Submit) -> Result { let db = DB.get().unwrap(); let mut conn = self.router.get(&submit.lang).await?; @@ -97,7 +185,7 @@ impl SubmitController { .order_by_asc(test::Column::Score) .all(db) .await?; - let (mut problem, testcases) = binding.pop().ok_or(Error::BadArgument("problem id"))?; + let (problem, testcases) = binding.pop().ok_or(Error::BadArgument("problem id"))?; // create uncommited submit let submit_model = submit::ActiveModel { @@ -113,9 +201,9 @@ impl SubmitController { .await?; let submit_id = submit_model.id.as_ref().to_owned(); - let mut pubguard = self.pubsub.publish(submit_id); + let tx = self.pubsub.publish(submit_id); - let mut scores = testcases.iter().rev().map(|x| x.score).collect::>(); + let scores = testcases.iter().rev().map(|x| x.score).collect::>(); let tests = testcases .into_iter() @@ -136,51 +224,8 @@ impl SubmitController { }) .await?; - tokio::spawn(async move { - let mut state = crate::controller::util::state::State::default(); - let mut res = res.into_inner(); - - while let Some(res) = res.next().await { - match res { - Ok(res) => { - state.parse_state(pubguard.borrow_mut(), res); - } - Err(err) => { - log::warn!("{}", err); - pubguard.send(Err(err)).ok(); - break; - } - } - } - let pass = state.pass == scores.len(); - let mut score = 0; - while let Some(x) = scores.pop() { - if state.pass == 0 { - break; - } - state.pass -= 1; - score += x; - } - - let mut submit_model = submit_model.into_active_model(); - submit_model.committed = ActiveValue::Set(true); - submit_model.time = ActiveValue::Set(Some(state.time)); - submit_model.memory = ActiveValue::Set(Some(state.mem)); - submit_model.score = ActiveValue::Set(score); + tokio::spawn(Self::stream(tx, res.into_inner(), submit_model, scores)); - problem.submit_count += 1; - if pass { - problem.accept_count += 1; - } - problem.ac_rate = problem.accept_count as f32 / problem.submit_count as f32; - - if let Err(err) = problem.into_active_model().save(db).await { - log::warn!("failed to update problem statistics: {}", err); - } - if let Err(err) = submit_model.save(db).await { - log::warn!("failed to commit the judge result: {}", err); - } - }); Ok(submit_id) } async fn follow(&self, submit_id: i32) -> Option> { diff --git a/backend/src/controller/token.rs b/backend/src/controller/token.rs index 7d69abae..f1d3c2d2 100644 --- a/backend/src/controller/token.rs +++ b/backend/src/controller/token.rs @@ -116,7 +116,7 @@ impl TokenController { // } // return Ok(None); // } - // #[instrument(skip_all, name = "token_verify")] + #[instrument(skip_all, name = "token_verify")] pub async fn verify(&self, token: &str) -> Result, Error> { let now = Local::now().naive_local(); let db = DB.get().unwrap(); diff --git a/backend/src/controller/util/code.rs b/backend/src/controller/util/code.rs new file mode 100644 index 00000000..ca73d18a --- /dev/null +++ b/backend/src/controller/util/code.rs @@ -0,0 +1,101 @@ +use crate::grpc::backend::StateCode as BackendCode; +use crate::grpc::judger::JudgerCode; + +#[repr(u32)] +pub enum Code { + Accepted = 1, + WrongAnswer = 2, + TimeLimitExceeded = 3, + MemoryLimitExceeded = 4, + RuntimeError = 5, + CompileError = 6, + SystemError = 7, + RestrictedFunction = 8, + Unknown = 9, + OutputLimitExceeded = 10, +} + +impl TryFrom for Code { + type Error = (); + + fn try_from(value: u32) -> Result { + match value { + 1 => Ok(Code::Accepted), + 2 => Ok(Code::WrongAnswer), + 3 => Ok(Code::TimeLimitExceeded), + 4 => Ok(Code::MemoryLimitExceeded), + 5 => Ok(Code::RuntimeError), + 6 => Ok(Code::CompileError), + 7 => Ok(Code::SystemError), + 8 => Ok(Code::RestrictedFunction), + 9 => Ok(Code::Unknown), + 10 => Ok(Code::OutputLimitExceeded), + _ => Err(()), + } + } +} + +impl From for JudgerCode { + fn from(value: Code) -> Self { + match value { + Code::Accepted => JudgerCode::Ac, + Code::WrongAnswer => JudgerCode::Wa, + Code::TimeLimitExceeded => JudgerCode::Tle, + Code::MemoryLimitExceeded => JudgerCode::Mle, + Code::RuntimeError => JudgerCode::Re, + Code::CompileError => JudgerCode::Ce, + Code::SystemError => JudgerCode::Na, + Code::RestrictedFunction => JudgerCode::Rf, + Code::Unknown => JudgerCode::Na, + Code::OutputLimitExceeded => JudgerCode::Ole, + } + } +} + +impl From for Code { + fn from(value: JudgerCode) -> Self { + match value { + JudgerCode::Re => Code::RuntimeError, + JudgerCode::Na => Code::Unknown, + JudgerCode::Wa => Code::WrongAnswer, + JudgerCode::Ce => Code::CompileError, + JudgerCode::Ac => Code::Accepted, + JudgerCode::Rf => Code::RestrictedFunction, + JudgerCode::Tle => Code::TimeLimitExceeded, + JudgerCode::Mle => Code::MemoryLimitExceeded, + JudgerCode::Ole => Code::OutputLimitExceeded, + } + } +} + +impl From for BackendCode { + fn from(value: Code) -> Self { + match value { + Code::Accepted => BackendCode::Ac, + Code::WrongAnswer => BackendCode::Wa, + Code::TimeLimitExceeded => BackendCode::Tle, + Code::MemoryLimitExceeded => BackendCode::Mle, + Code::RuntimeError => BackendCode::Re, + Code::CompileError => BackendCode::Ce, + Code::SystemError => BackendCode::Na, + Code::RestrictedFunction => BackendCode::Rf, + Code::Unknown => BackendCode::Na, + Code::OutputLimitExceeded => BackendCode::Ole, + } + } +} +impl From for Code { + fn from(value: BackendCode) -> Self { + match value { + BackendCode::Ac => Code::Accepted, + BackendCode::Wa => Code::WrongAnswer, + BackendCode::Tle => Code::TimeLimitExceeded, + BackendCode::Mle => Code::MemoryLimitExceeded, + BackendCode::Re => Code::RuntimeError, + BackendCode::Ce => Code::CompileError, + BackendCode::Na => Code::SystemError, + BackendCode::Rf => Code::RestrictedFunction, + BackendCode::Ole => Code::OutputLimitExceeded, + } + } +} diff --git a/backend/src/controller/util/mod.rs b/backend/src/controller/util/mod.rs index 5de094bf..0895b062 100644 --- a/backend/src/controller/util/mod.rs +++ b/backend/src/controller/util/mod.rs @@ -1,3 +1,3 @@ +pub mod code; pub mod pubsub; pub mod router; -pub mod state; diff --git a/backend/src/controller/util/state.rs b/backend/src/controller/util/state.rs deleted file mode 100644 index 93f87828..00000000 --- a/backend/src/controller/util/state.rs +++ /dev/null @@ -1,87 +0,0 @@ -use std::cmp; - -use tokio::sync::broadcast::*; - -use crate::grpc::backend::{ - self, judge_result, submit_status, StateCode as BackendCode, SubmitStatus, -}; -use crate::grpc::judger::{judge_response, JudgeResponse, JudgeResultState as JudgeCode}; - -impl Into for JudgeCode { - fn into(self) -> BackendCode { - match self { - JudgeCode::Ac => BackendCode::Ac, - JudgeCode::Wa => BackendCode::Wa, - JudgeCode::Tle => BackendCode::Tle, - JudgeCode::Mle => BackendCode::Mle, - JudgeCode::Re => BackendCode::Re, - JudgeCode::Ce => BackendCode::Ce, - JudgeCode::Ole => BackendCode::Ole, - JudgeCode::Na => BackendCode::Na, - JudgeCode::Rf => BackendCode::Rf, - } - } -} - -impl Into for BackendCode { - fn into(self) -> JudgeCode { - match self { - BackendCode::Ac => JudgeCode::Ac, - BackendCode::Wa => JudgeCode::Wa, - BackendCode::Tle => JudgeCode::Tle, - BackendCode::Mle => JudgeCode::Mle, - BackendCode::Re => JudgeCode::Re, - BackendCode::Ce => JudgeCode::Ce, - BackendCode::Ole => JudgeCode::Ole, - BackendCode::Na => JudgeCode::Na, - BackendCode::Rf => JudgeCode::Rf, - } - } -} - -#[derive(Default)] -pub struct State { - pub time: u64, - pub mem: u64, - pub pass: usize, -} - -impl State { - pub fn parse_state( - &mut self, - tx: &mut Sender>, - res: JudgeResponse, - ) { - if res.task.is_none() { - log::warn!("mismatch proto(judger)"); - return; - } - match res.task.unwrap() { - judge_response::Task::Case(case) => { - tx.send(Ok(SubmitStatus { - task: Some(submit_status::Task::Case(case)), - })) - .ok(); - } - judge_response::Task::Result(res) => { - tx.send(Ok(SubmitStatus { - // TODO: rework the judger.proto - task: Some(submit_status::Task::Result(backend::JudgeResult { - info: Some(judge_result::Info::Committed(judge_result::Committed { - code: JudgeCode::from_i32(res.status).unwrap_or_default().into(), - accuracy: res.accuracy, - time: res.max_time, - memory: res.max_mem, - })), - })), - })) - .ok(); - self.time = cmp::max(self.time, res.max_time); - self.mem = cmp::max(self.mem, res.max_mem); - if res.status() == JudgeCode::Ac { - self.pass += 1; - } - } - } - } -} diff --git a/backend/src/endpoint/submit.rs b/backend/src/endpoint/submit.rs index 0f643111..c6806701 100644 --- a/backend/src/endpoint/submit.rs +++ b/backend/src/endpoint/submit.rs @@ -3,8 +3,11 @@ use super::tools::*; use super::util::stream::*; use super::util::time::into_prost; +use crate::controller::util::code::Code; use crate::grpc::backend::submit_set_server::*; +use crate::grpc::backend::StateCode as BackendCode; use crate::grpc::backend::*; +use crate::grpc::judger::JudgerCode; use entity::{submit::*, *}; @@ -38,15 +41,17 @@ impl From for i32 { impl From for SubmitInfo { fn from(value: Model) -> Self { // TODO: solve devation aand uncommitted submit! - let state: JudgeResult = match value.committed { - true => todo!(), - false => todo!(), - }; + let db_code: Code = value.status.try_into().unwrap(); SubmitInfo { id: value.id.into(), upload_time: into_prost(value.upload_at), score: value.score, - state, + state: JudgeResult { + code: Into::::into(db_code).into(), + accuracy: value.accuracy, + time: value.time, + memory: value.memory, + }, } } } @@ -86,11 +91,38 @@ impl SubmitSet for Arc { &self, req: Request, ) -> Result, tonic::Status> { - todo!() + let (auth, req) = self.parse_request(req).await?; + + let mut reverse = false; + let mut pager: Pager = match req.request.ok_or(Error::NotInPayload("request"))? { + list_by_request::Request::ParentId(ppk) => Pager::parent_search(ppk), + list_by_request::Request::Pager(old) => { + reverse = old.reverse; + as HasParentPager>::from_raw(old.session)? + } + }; + + let list = pager + .fetch(req.size, req.offset.unwrap_or_default(), reverse, &auth) + .await? + .into_iter() + .map(|x| x.into()) + .collect(); + + let next_session = pager.into_raw(); + + Ok(Response::new(ListSubmitResponse { list, next_session })) } async fn info(&self, req: Request) -> Result, Status> { - todo!() + let db = DB.get().unwrap(); + let (auth, req) = self.parse_request(req).await?; + + let model=Entity::read_filter(Entity::find_by_id(req.id), &auth)? + .one(db) + .await.map_err(Into::::into)?.ok_or(Error::NotInDB("submit"))?; + + Ok(Response::new(model.into())) } async fn create( diff --git a/judger/src/grpc/proto.rs b/judger/src/grpc/proto.rs index 1c04c64c..b8d70575 100644 --- a/judger/src/grpc/proto.rs +++ b/judger/src/grpc/proto.rs @@ -4,19 +4,20 @@ pub mod prelude { use std::fmt::Display; -impl Display for prelude::JudgeResultState { +impl Display for prelude::JudgerCode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let message = match self { - prelude::JudgeResultState::Ac => "Accepted", - prelude::JudgeResultState::Na => "Unknown", - prelude::JudgeResultState::Wa => "Wrong Answer", - prelude::JudgeResultState::Ce => "Compile Error", - prelude::JudgeResultState::Re => "Runtime Error", - prelude::JudgeResultState::Rf => "Restricted Function", - prelude::JudgeResultState::Tle => "Time Limit Excess", - prelude::JudgeResultState::Mle => "Memory Limit Excess", - prelude::JudgeResultState::Ole => "Output Limit Excess", + prelude::JudgerCode::Ac => "Accepted", + prelude::JudgerCode::Na => "Unknown", + prelude::JudgerCode::Wa => "Wrong Answer", + prelude::JudgerCode::Ce => "Compile Error", + prelude::JudgerCode::Re => "Runtime Error", + prelude::JudgerCode::Rf => "Restricted Function", + prelude::JudgerCode::Tle => "Time Limit Excess", + prelude::JudgerCode::Mle => "Memory Limit Excess", + prelude::JudgerCode::Ole => "Output Limit Excess", }; write!(f, "{}", message) } } + \ No newline at end of file diff --git a/judger/src/grpc/server.rs b/judger/src/grpc/server.rs index 07517a78..edae2761 100644 --- a/judger/src/grpc/server.rs +++ b/judger/src/grpc/server.rs @@ -61,8 +61,8 @@ macro_rules! report { $tx.send(Ok(JudgeResponse { task: Some(judge_response::Task::Result(JudgeResult { status: res as i32, - max_time: 0, - max_mem: 0, + time: 0, + memory: 0, accuracy: accuracy(), })), })) @@ -134,7 +134,6 @@ impl Judger for Server { .await .ok(); - running_task += 1; let result = report!(compiled.judge(&task.input, time, memory).await, tx); @@ -142,8 +141,8 @@ impl Judger for Server { tx.send(Ok(JudgeResponse { task: Some(judge_response::Task::Result(JudgeResult { status: x as i32, - max_time: result.time().total_us, - max_mem: result.mem().peak, + time: result.time().total_us, + memory: result.mem().peak, accuracy: accuracy(), })), })) @@ -155,16 +154,17 @@ impl Judger for Server { tx.send(Ok(JudgeResponse { task: Some(judge_response::Task::Result(JudgeResult { status: match result.assert(&task.output, mode) { - true => JudgeResultState::Ac, - false => JudgeResultState::Wa, - } as i32, - max_time: result.time().total_us, - max_mem: result.mem().peak, + true => JudgerCode::Ac, + false => JudgerCode::Wa, + } as i32, + time: result.time().total_us, + memory: result.mem().peak, accuracy: accuracy(), })), })) .await .ok(); + running_task += 1; } }); diff --git a/judger/src/langs/artifact.rs b/judger/src/langs/artifact.rs index d752594e..5a86f66a 100644 --- a/judger/src/langs/artifact.rs +++ b/judger/src/langs/artifact.rs @@ -94,7 +94,7 @@ impl ArtifactFactory { let process = process.wait().await?; if !process.succeed() { - return Err(Error::Report(JudgeResultState::Ce)); + return Err(Error::Report(JudgerCode::Ce)); } Ok(CompiledArtifact { @@ -152,7 +152,7 @@ impl<'a> CompiledArtifact<'a> { let process = process.wait().await?; if !process.succeed() { - return Err(Error::Report(JudgeResultState::Re)); + return Err(Error::Report(JudgerCode::Re)); } Ok(TaskResult { @@ -169,17 +169,17 @@ pub struct TaskResult { } impl TaskResult { - pub fn get_expection(&self) -> Option { + pub fn get_expection(&self) -> Option { match self.process.status { - ExitStatus::SigExit => Some(JudgeResultState::Rf), + ExitStatus::SigExit => Some(JudgerCode::Rf), ExitStatus::Code(code) => match code { 0 | 5 | 6 | 9 | 255 => None, - 137 => Some(JudgeResultState::Na), - _ => Some(JudgeResultState::Rf), + 137 => Some(JudgerCode::Na), + _ => Some(JudgerCode::Rf), }, - ExitStatus::MemExhausted => Some(JudgeResultState::Mle), - ExitStatus::CpuExhausted => Some(JudgeResultState::Tle), - ExitStatus::SysError => Some(JudgeResultState::Na), + ExitStatus::MemExhausted => Some(JudgerCode::Mle), + ExitStatus::CpuExhausted => Some(JudgerCode::Tle), + ExitStatus::SysError => Some(JudgerCode::Na), } } pub fn assert(&self, input: &[u8], mode: JudgeMatchRule) -> bool { diff --git a/judger/src/langs/mod.rs b/judger/src/langs/mod.rs index c5ec710d..0151ae77 100644 --- a/judger/src/langs/mod.rs +++ b/judger/src/langs/mod.rs @@ -1,6 +1,6 @@ use thiserror::Error; -use crate::{grpc::proto::prelude::JudgeResultState, sandbox}; +use crate::{grpc::proto::prelude::JudgerCode, sandbox}; pub mod artifact; pub mod spec; @@ -35,7 +35,7 @@ pub enum Error { #[error("Bad Request: `{0}`")] BadRequest(#[from] RequestError), #[error("Report the result to client")] - Report(JudgeResultState), + Report(JudgerCode), } impl From for Error { @@ -43,12 +43,12 @@ impl From for Error { match value { sandbox::Error::ImpossibleResource | sandbox::Error::Stall - | sandbox::Error::CapturedPipe => Error::Report(JudgeResultState::Re), + | sandbox::Error::CapturedPipe => Error::Report(JudgerCode::Re), sandbox::Error::IO(_) | sandbox::Error::ControlGroup(_) | sandbox::Error::Libc(_) | sandbox::Error::CGroup => Error::Internal(InternalError::JailError(value)), - sandbox::Error::BufferFull => Error::Report(JudgeResultState::Ole), + sandbox::Error::BufferFull => Error::Report(JudgerCode::Ole), } } } diff --git a/judger/src/sandbox/utils/semaphore.rs b/judger/src/sandbox/utils/semaphore.rs index e95217d1..f36d3047 100644 --- a/judger/src/sandbox/utils/semaphore.rs +++ b/judger/src/sandbox/utils/semaphore.rs @@ -16,7 +16,7 @@ static MEMID: atomic::AtomicUsize = atomic::AtomicUsize::new(0); pub struct MemoryStatistic { pub available_mem: u64, - pub max_mem: u64, + pub memory: u64, pub tasks: u64, } @@ -39,7 +39,7 @@ impl MemorySemaphore { let self_ = self.0.lock(); MemoryStatistic { available_mem: self_.memory, - max_mem: self_.all_mem, + memory: self_.all_mem, tasks: self_.tasks, } } diff --git a/judger/src/test/grpc.rs b/judger/src/test/grpc.rs index 67ad1268..4e779399 100644 --- a/judger/src/test/grpc.rs +++ b/judger/src/test/grpc.rs @@ -65,7 +65,7 @@ async fn full() { match res2.unwrap() { Task::Case(_) => panic!("expect Result"), Task::Result(result) => { - assert_eq!(result.status, JudgeResultState::Ac as i32); + assert_eq!(result.status, JudgerCode::Ac as i32); } } server.abort(); diff --git a/proto/backend.proto b/proto/backend.proto index 8790aa84..d5293cfe 100644 --- a/proto/backend.proto +++ b/proto/backend.proto @@ -102,19 +102,10 @@ enum StateCode{ OLE = 8; } message JudgeResult { - message Uncommitted{ - - } - message Committed{ required StateCode code=1; - required uint64 accuracy=2; - required uint64 time=3; - required uint64 memory=4; - } - oneof info{ - Uncommitted uncommitted=1; - Committed committed =2; - }; + optional uint64 accuracy=2; + optional uint64 time=3; + optional uint64 memory=4; } message SubmitId { required int32 id = 1; } diff --git a/proto/judger.proto b/proto/judger.proto index e0fb731d..d7faa184 100644 --- a/proto/judger.proto +++ b/proto/judger.proto @@ -31,16 +31,16 @@ message JudgeResponse { message JudgeResult { // assertion code - required JudgeResultState status = 1; + required JudgerCode status = 1; // the time in nanosecond - required uint64 max_time = 2; + required uint64 time = 2; // the peak memory usage - required uint64 max_mem = 3; + required uint64 memory = 3; // max possible deviation in nanosecond required uint64 accuracy = 4; } -enum JudgeResultState { +enum JudgerCode { // Runtime Error RE = 0; // Unknown