Compare commits
3 Commits
master
...
docs/READM
Author | SHA1 | Date | |
---|---|---|---|
139eafa644 | |||
8ebc432999 | |||
2a6428feec |
|
@ -23,9 +23,9 @@ jobs:
|
|||
- name: PDM install dependencies
|
||||
run: |
|
||||
pdm install
|
||||
- name: All
|
||||
- name: Lint
|
||||
run: |
|
||||
pdm run all
|
||||
pdm run lint
|
||||
- name: Run
|
||||
run: |
|
||||
pdm run app --help
|
||||
|
|
66
README.md
66
README.md
|
@ -1,8 +1,12 @@
|
|||
# JOJ3-config-generator
|
||||
# JOJ3-forge
|
||||
|
||||
[](https://app.codacy.com/gh/joint-online-judge/JOJ3-config-generator/dashboard)
|
||||
[](https://app.codacy.com/gh/joint-online-judge/JOJ3-config-generator/dashboard)
|
||||
|
||||
## Introduction
|
||||
|
||||
JOJ3-forge is a CLI tool that generates configuration files for [JOJ3](https://github.com/joint-online-judge/JOJ3).
|
||||
|
||||
## Getting Started
|
||||
|
||||
### For users
|
||||
|
@ -10,7 +14,7 @@
|
|||
1. Install [Python>=3.9](https://www.python.org/) and [pip](https://pip.pypa.io/)
|
||||
2. (Optional) Create a virtual environment, check [here](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/).
|
||||
3. Install/Upgrade the project by `pip install --force-reinstall --upgrade git+ssh://git@focs.ji.sjtu.edu.cn:2222/JOJ/JOJ3-config-generator.git`
|
||||
4. Run it by `joj3-config-generator --help`
|
||||
4. Run it by `joj3-forge --help`
|
||||
|
||||
### For developers
|
||||
|
||||
|
@ -23,22 +27,62 @@
|
|||
|
||||
## How to use?
|
||||
|
||||
- `joj3-config-generator convert` function is now supported, currently support one argument as input, it indicates the **convert root**
|
||||
- default value on the server can be given as `/home/tt/.config/joj`
|
||||
Run `joj3-forge --help` to get basic CLI usage information.
|
||||
|
||||
### `convert`
|
||||
|
||||
- `joj3-forge convert` function is now supported, currently support one argument as input, it indicates the **convert root*
|
||||
- default value on the server should be given as `/home/tt/.config/joj`
|
||||
- **NOTE:** the user should ensure that the ideal `repo.toml` file is in the sub-directory of the **convert root**
|
||||
- the intended immutable files should be placed at a sub-directory named `immutable_files` at same position as the `repo.toml` file
|
||||
- a sample directory tree as follows
|
||||
|
||||
```shell
|
||||
$ tree .
|
||||
.
|
||||
|- immutable_files
|
||||
| |-- push.yaml
|
||||
| |-- release.yaml
|
||||
|-- repo.toml
|
||||
$ tree -a
|
||||
home
|
||||
`-- tt
|
||||
|-- .cache
|
||||
`-- .config
|
||||
`-- joj
|
||||
|-- hidden
|
||||
| |-- ex1
|
||||
| | |-- case1.in
|
||||
| | |-- case1.out
|
||||
| | |-- conf.json
|
||||
| | `-- conf.toml
|
||||
| |-- immutable_files
|
||||
| | |-- push.yaml
|
||||
| | `-- release.yaml
|
||||
| |-- p1
|
||||
| | |-- case1.in
|
||||
| | |-- case1.out
|
||||
| | |-- conf.json
|
||||
| | `-- conf.toml
|
||||
| `-- repo.toml
|
||||
|-- students
|
||||
| |-- ex1
|
||||
| | |-- case1.in
|
||||
| | |-- case1.out
|
||||
| | |-- conf.json
|
||||
| | `-- conf.toml
|
||||
| |-- immutable_files
|
||||
| | |-- push.yaml
|
||||
| | `-- release.yaml
|
||||
| |-- p1
|
||||
| | |-- case1.in
|
||||
| | |-- case1.out
|
||||
| | |-- conf.json
|
||||
| | `-- conf.toml
|
||||
| `-- repo.toml
|
||||
|-- students.csv
|
||||
`-- tools
|
||||
|-- .clang-tidy
|
||||
|-- compile
|
||||
`-- helper.sh
|
||||
```
|
||||
|
||||
- sample command on the server
|
||||
|
||||
```shell
|
||||
joj3-config-generator convert /home/tt/.config/joj
|
||||
joj3-forge convert /home/tt/.config/joj
|
||||
```
|
||||
|
|
|
@ -26,8 +26,8 @@ def convert_joj3_conf(repo_conf: repo.Config, task_conf: task.Config) -> result.
|
|||
name=task_conf.task.name,
|
||||
# exact folder difference specified by type
|
||||
log_path=str(JOJ3_LOG_PATH),
|
||||
expire_unix_timestamp=0, # will be handled in the health check stage
|
||||
effective_unix_timestamp=0, # will be handled in the health check stage
|
||||
expire_unix_timestamp=int(task_conf.release.end_time.timestamp()),
|
||||
effective_unix_timestamp=int(task_conf.release.begin_time.timestamp()),
|
||||
actor_csv_path=str(ACTOR_CSV_PATH), # students.csv position
|
||||
max_total_score=(
|
||||
repo_conf.max_total_score
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import os
|
||||
import socket
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from pydantic import AliasChoices, BaseModel, Field, model_validator
|
||||
from pydantic import AliasChoices, BaseModel, Field
|
||||
|
||||
|
||||
class Files(BaseModel):
|
||||
|
@ -20,18 +20,6 @@ class Groups(BaseModel):
|
|||
)
|
||||
|
||||
|
||||
class Label(BaseModel):
|
||||
name: str = "Kind/Testing"
|
||||
color: str = "#795548"
|
||||
|
||||
|
||||
class Issue(BaseModel):
|
||||
label: Label = Label()
|
||||
show_submitter: bool = Field(
|
||||
True, validation_alias=AliasChoices("show-submitter", "show_submitter")
|
||||
)
|
||||
|
||||
|
||||
class Config(BaseModel):
|
||||
max_size: float = Field(
|
||||
10, ge=0, validation_alias=AliasChoices("max-size", "max_size")
|
||||
|
@ -40,10 +28,6 @@ class Config(BaseModel):
|
|||
sandbox_token: str = Field(
|
||||
"", validation_alias=AliasChoices("sandbox-token", "sandbox_token")
|
||||
)
|
||||
gitea_token: str = Field(
|
||||
"", validation_alias=AliasChoices("gitea-token", "gitea_token")
|
||||
)
|
||||
gitea_org: str = Field("", validation_alias=AliasChoices("gitea-org", "gitea_org"))
|
||||
max_total_score: int = Field(
|
||||
100, validation_alias=AliasChoices("max-total-score", "max_total_score")
|
||||
)
|
||||
|
@ -63,24 +47,15 @@ class Config(BaseModel):
|
|||
root: Path = Path(".")
|
||||
path: Path = Path("repo.toml")
|
||||
grading_repo_name: str = Field(
|
||||
"",
|
||||
f"{socket.gethostname().split('-')[0]}-joj",
|
||||
validation_alias=AliasChoices("grading-repo-name", "grading_repo_name"),
|
||||
)
|
||||
health_check_score: int = Field(
|
||||
0, validation_alias=AliasChoices("health-check-score", "health_check_score")
|
||||
)
|
||||
issue: Issue = Issue()
|
||||
immutable_path: Path = Field(
|
||||
Path("immutable_files"),
|
||||
validation_alias=AliasChoices("immutable-path", "immutable_path"),
|
||||
submitter_in_issue_title: bool = Field(
|
||||
True,
|
||||
validation_alias=AliasChoices(
|
||||
"submitter-in-issue-title", "submitter_in_issue_title"
|
||||
),
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def set_grading_repo_name_from_cwd(self) -> "Config":
|
||||
if not self.grading_repo_name:
|
||||
course_env = os.getenv("COURSE")
|
||||
if course_env:
|
||||
self.grading_repo_name = f"{course_env}-joj"
|
||||
else:
|
||||
self.grading_repo_name = Path.cwd().name
|
||||
return self
|
||||
|
|
|
@ -177,12 +177,6 @@ class Config(BaseModel):
|
|||
|
||||
|
||||
class DummyConfig(BaseModel):
|
||||
score: int = 0
|
||||
comment: Optional[str] = None
|
||||
force_quit: Optional[bool] = Field(False, serialization_alias="forceQuit")
|
||||
|
||||
|
||||
class ResultStatusConfig(BaseModel):
|
||||
score: int = 0
|
||||
comment: Optional[str] = None
|
||||
force_quit_on_not_accepted: Optional[bool] = Field(
|
||||
|
@ -192,7 +186,7 @@ class ResultStatusConfig(BaseModel):
|
|||
|
||||
class DiffOutputConfig(BaseModel):
|
||||
score: int = 100
|
||||
filename: str = Field("", serialization_alias="filename")
|
||||
file_name: str = Field("", serialization_alias="fileName")
|
||||
answer_path: str = Field("", serialization_alias="answerPath")
|
||||
compare_space: bool = Field(False, serialization_alias="compareSpace")
|
||||
always_hide: bool = Field(False, serialization_alias="alwaysHide")
|
||||
|
@ -223,7 +217,6 @@ class KeywordConfig(BaseModel):
|
|||
|
||||
|
||||
class KeywordMatchConfig(BaseModel):
|
||||
score: int = 0
|
||||
matches: List[KeywordConfig] = []
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import re
|
||||
from datetime import datetime, timezone
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional, Type
|
||||
from typing import Any, Dict, List, Type
|
||||
|
||||
from pydantic import (
|
||||
AliasChoices,
|
||||
|
@ -39,12 +38,6 @@ class ParserResultDetail(BaseModel):
|
|||
False, validation_alias=AliasChoices("proc-peak", "proc_peak")
|
||||
) # Display peak process count
|
||||
error: bool = False # Display error messages
|
||||
code_block: bool = Field(
|
||||
True, validation_alias=AliasChoices("code-block", "code_block")
|
||||
) # Display file in code block
|
||||
max_length: int = Field(
|
||||
2048, validation_alias=AliasChoices("max-length", "max_length")
|
||||
) # Max output length of each file
|
||||
|
||||
|
||||
class ParserFile(BaseModel):
|
||||
|
@ -65,16 +58,7 @@ class ParserDummy(BaseModel):
|
|||
)
|
||||
|
||||
|
||||
class ParserResultStatus(BaseModel):
|
||||
comment: str = ""
|
||||
score: int = 0
|
||||
force_quit: bool = Field(
|
||||
True, validation_alias=AliasChoices("force-quit", "force_quit")
|
||||
)
|
||||
|
||||
|
||||
class ParserKeyword(BaseModel):
|
||||
score: int = 0
|
||||
keyword: List[str] = []
|
||||
weight: List[int] = []
|
||||
|
||||
|
@ -98,39 +82,12 @@ class ParserDiffOutputs(BaseModel):
|
|||
|
||||
|
||||
class ParserDiff(BaseModel):
|
||||
score: int = DEFAULT_CASE_SCORE
|
||||
ignore_spaces: bool = Field(
|
||||
True, validation_alias=AliasChoices("ignore-spaces", "ignore_spaces")
|
||||
)
|
||||
hide: bool = False
|
||||
force_quit: bool = Field(
|
||||
False, validation_alias=AliasChoices("force-quit", "force_quit")
|
||||
)
|
||||
max_length: int = Field(
|
||||
2048, validation_alias=AliasChoices("max-length", "max_length")
|
||||
)
|
||||
max_lines: int = Field(50, validation_alias=AliasChoices("max-lines", "max_lines"))
|
||||
hide_common_prefix: bool = Field(
|
||||
False, validation_alias=AliasChoices("hide-common-prefix", "hide_common_prefix")
|
||||
)
|
||||
# remove below codes when migration is complete
|
||||
output: ParserDiffOutputs = ParserDiffOutputs()
|
||||
default_score: int = Field(
|
||||
DEFAULT_CASE_SCORE,
|
||||
validation_alias=AliasChoices("default-score", "default_score"),
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def copy_output_fields(self) -> "ParserDiff":
|
||||
if "default_score" in self.model_fields_set:
|
||||
self.score = self.default_score
|
||||
if not isinstance(self.output, ParserDiffOutputs):
|
||||
return self
|
||||
for field_name, field_value in self.output.model_dump().items():
|
||||
if field_name in self.output.model_fields_set and hasattr(self, field_name):
|
||||
setattr(self, field_name, field_value)
|
||||
return self
|
||||
|
||||
|
||||
class StageFiles(BaseModel):
|
||||
import_: List[str] = Field([], validation_alias="import")
|
||||
|
@ -184,6 +141,7 @@ class Case(BaseModel):
|
|||
True, validation_alias=AliasChoices("copy-in-cwd", "copy_in_cwd")
|
||||
)
|
||||
limit: Limit = Limit()
|
||||
score: int = 0
|
||||
diff: ParserDiff = ParserDiff()
|
||||
|
||||
|
||||
|
@ -193,9 +151,8 @@ class Stage(Case):
|
|||
|
||||
parsers: List[Parser] = [] # list of parsers
|
||||
dummy: ParserDummy = ParserDummy()
|
||||
result_status: ParserResultStatus = Field(
|
||||
ParserResultStatus(),
|
||||
validation_alias=AliasChoices("result-status", "result_status"),
|
||||
result_status: ParserDummy = Field(
|
||||
ParserDummy(), validation_alias=AliasChoices("result-status", "result_status")
|
||||
)
|
||||
keyword: ParserKeyword = ParserKeyword()
|
||||
clangtidy: ParserKeyword = ParserKeyword()
|
||||
|
@ -207,7 +164,6 @@ class Stage(Case):
|
|||
validation_alias=AliasChoices("result-detail", "result_detail"),
|
||||
)
|
||||
file: ParserFile = ParserFile()
|
||||
# diff: ParserDiff = ParserDiff() # inherited from Case
|
||||
|
||||
cases: Dict[str, Case] = {}
|
||||
|
||||
|
@ -239,37 +195,17 @@ class Release(BaseModel):
|
|||
) # timestamp = 0, no begin time
|
||||
|
||||
|
||||
class SubmissionTime(BaseModel):
|
||||
begin: Optional[datetime] = None
|
||||
end: Optional[datetime] = None
|
||||
|
||||
|
||||
class Task(BaseModel):
|
||||
name: str = "unknown"
|
||||
|
||||
|
||||
class Penalties(BaseModel):
|
||||
hours: List[float] = []
|
||||
factors: List[float] = []
|
||||
|
||||
|
||||
class Config(BaseModel):
|
||||
root: Path = Path(".")
|
||||
path: Path = Path("task.toml")
|
||||
task: Task = Task() # Task name (e.g., hw3 ex5)
|
||||
time: SubmissionTime = SubmissionTime() # Valid time configuration
|
||||
release: Release = Release() # Release configuration
|
||||
stages: List[Stage] = [] # list of stage configurations
|
||||
groups: Groups = Groups()
|
||||
penalties: Penalties = Penalties()
|
||||
max_total_score: Optional[int] = Field(
|
||||
None, validation_alias=AliasChoices("max-total-score", "max_total_score")
|
||||
max_total_score: int = Field(
|
||||
100, validation_alias=AliasChoices("max-total-score", "max_total_score")
|
||||
)
|
||||
scoreboard: str = "scoreboard.csv"
|
||||
|
||||
@model_validator(mode="after")
|
||||
def set_scoreboard(self) -> "Config":
|
||||
if self.scoreboard == "auto":
|
||||
suffix = re.split(r"[-_/\s]+", self.task.name)[0]
|
||||
self.scoreboard = f"scoreboard-{suffix}.csv"
|
||||
return self
|
||||
|
|
|
@ -1,26 +1,9 @@
|
|||
import hashlib
|
||||
from pathlib import Path
|
||||
from typing import List, Tuple
|
||||
from typing import List
|
||||
|
||||
from joj3_config_generator.models import common, repo, result, task
|
||||
from joj3_config_generator.models.const import (
|
||||
CACHE_ROOT,
|
||||
TEAPOT_CONFIG_ROOT,
|
||||
TEAPOT_LOG_PATH,
|
||||
)
|
||||
from joj3_config_generator.utils.logger import logger
|
||||
|
||||
|
||||
def get_teapot_env(repo_conf: repo.Config) -> List[str]:
|
||||
res = [
|
||||
f"REPOS_DIR={CACHE_ROOT}",
|
||||
f"LOG_FILE_PATH={TEAPOT_LOG_PATH}",
|
||||
]
|
||||
if repo_conf.gitea_org:
|
||||
res.append(f"GITEA_ORG_NAME={repo_conf.gitea_org}")
|
||||
if repo_conf.gitea_token:
|
||||
res.append(f"GITEA_ACCESS_TOKEN={repo_conf.gitea_token}")
|
||||
return res
|
||||
from joj3_config_generator.models.const import TEAPOT_CONFIG_ROOT, TEAPOT_LOG_PATH
|
||||
|
||||
|
||||
def get_teapot_post_stage(
|
||||
|
@ -34,34 +17,13 @@ def get_teapot_post_stage(
|
|||
repo_conf.grading_repo_name,
|
||||
"--max-total-score",
|
||||
(
|
||||
str(task_conf.max_total_score)
|
||||
if task_conf.max_total_score is not None
|
||||
else str(repo_conf.max_total_score)
|
||||
str(repo_conf.max_total_score)
|
||||
if not task_conf.max_total_score
|
||||
else str(task_conf.max_total_score)
|
||||
),
|
||||
"--issue-label-name",
|
||||
repo_conf.issue.label.name,
|
||||
"--issue-label-color",
|
||||
repo_conf.issue.label.color,
|
||||
"--scoreboard-filename",
|
||||
task_conf.scoreboard,
|
||||
]
|
||||
if not repo_conf.issue.show_submitter:
|
||||
if not repo_conf.submitter_in_issue_title:
|
||||
args.append("--no-submitter-in-issue-title")
|
||||
if task_conf.time.end:
|
||||
args.extend(
|
||||
[
|
||||
"--end-time",
|
||||
task_conf.time.end.strftime("%Y-%m-%dT%H:%M:%S"),
|
||||
]
|
||||
)
|
||||
if task_conf.penalties.hours:
|
||||
penalty_config = ",".join(
|
||||
f"{hour}={factor}"
|
||||
for hour, factor in zip(
|
||||
task_conf.penalties.hours, task_conf.penalties.factors
|
||||
)
|
||||
)
|
||||
args.extend(["--penalty-config", penalty_config])
|
||||
|
||||
stage_conf = result.StageDetail(
|
||||
name="teapot",
|
||||
|
@ -70,7 +32,7 @@ def get_teapot_post_stage(
|
|||
with_=result.ExecutorWith(
|
||||
default=result.Cmd(
|
||||
args=args,
|
||||
env=get_teapot_env(repo_conf),
|
||||
env=[f"LOG_FILE_PATH={TEAPOT_LOG_PATH}"],
|
||||
cpu_limit=common.Time("30s"),
|
||||
clock_limit=common.Time("60s"),
|
||||
),
|
||||
|
@ -85,45 +47,14 @@ def get_teapot_post_stage(
|
|||
return stage_conf
|
||||
|
||||
|
||||
def get_check_lists(repo_conf: repo.Config) -> Tuple[List[str], List[str]]:
|
||||
base_dir = (repo_conf.root / repo_conf.path).parent
|
||||
immutable_dir = base_dir / "immutable_files"
|
||||
immutable_files = []
|
||||
file_sums = []
|
||||
file_names = []
|
||||
for file in repo_conf.files.immutable:
|
||||
file_path = immutable_dir / Path(file).name
|
||||
if not file_path.exists():
|
||||
logger.warning(f"Immutable file not found: {file_path}")
|
||||
continue
|
||||
immutable_files.append(file_path)
|
||||
file_sums.append(calc_sha256sum(file_path))
|
||||
file_names.append(file)
|
||||
immutable_dir = (repo_conf.root / repo_conf.path).parent / repo_conf.immutable_path
|
||||
if not immutable_dir.exists():
|
||||
return file_sums, file_names
|
||||
file_sums = []
|
||||
file_names = []
|
||||
for file_path in sorted(immutable_dir.glob("**/*")):
|
||||
if file_path.is_dir():
|
||||
continue
|
||||
if not file_path.exists():
|
||||
logger.warning(f"Immutable file not found: {file_path}")
|
||||
continue
|
||||
file_sums.append(calc_sha256sum(file_path))
|
||||
file_names.append(file_path.relative_to(immutable_dir).as_posix())
|
||||
return file_sums, file_names
|
||||
|
||||
|
||||
def get_health_check_args(repo_conf: repo.Config) -> List[str]:
|
||||
file_sums, file_names = get_check_lists(repo_conf)
|
||||
return [
|
||||
"/usr/local/bin/repo-health-checker",
|
||||
"-root=.",
|
||||
f"-repoSize={str(repo_conf.max_size)}",
|
||||
*[f"-meta={meta}" for meta in repo_conf.files.required],
|
||||
f"-checkFileSumList={','.join(file_sums)}",
|
||||
f"-checkFileNameList={','.join(file_names)}",
|
||||
f"-checkFileSumList={','.join(get_hashes(repo_conf))}",
|
||||
f"-checkFileNameList={','.join(repo_conf.files.immutable)}",
|
||||
]
|
||||
|
||||
|
||||
|
@ -134,34 +65,28 @@ def get_teapot_check_args(repo_conf: repo.Config, task_conf: task.Config) -> Lis
|
|||
str(TEAPOT_CONFIG_ROOT / "teapot.env"),
|
||||
"--grading-repo-name",
|
||||
repo_conf.grading_repo_name,
|
||||
"--scoreboard-filename",
|
||||
task_conf.scoreboard,
|
||||
]
|
||||
if repo_conf.groups.name:
|
||||
group_str = lambda groups: ",".join(
|
||||
group_config_str = ",".join(
|
||||
f"{name}={max_count}:{time_period}"
|
||||
for name, max_count, time_period in zip(
|
||||
groups.name,
|
||||
groups.max_count,
|
||||
groups.time_period_hour,
|
||||
repo_conf.groups.name,
|
||||
repo_conf.groups.max_count,
|
||||
repo_conf.groups.time_period_hour,
|
||||
)
|
||||
)
|
||||
group_config = group_str(
|
||||
task_conf.groups if task_conf.groups.name else repo_conf.groups
|
||||
)
|
||||
res.extend(["--group-config", group_config])
|
||||
if task_conf.time.begin:
|
||||
res.extend(["--begin-time", task_conf.time.begin.strftime("%Y-%m-%dT%H:%M:%S")])
|
||||
if task_conf.time.end:
|
||||
res.extend(["--end-time", task_conf.time.end.strftime("%Y-%m-%dT%H:%M:%S")])
|
||||
if task_conf.penalties.hours:
|
||||
penalty_config = ",".join(
|
||||
f"{hour}={factor}"
|
||||
for hour, factor in zip(
|
||||
task_conf.penalties.hours, task_conf.penalties.factors
|
||||
if task_conf.groups.name:
|
||||
overwrite_group_config_str = ",".join(
|
||||
f"{name}={max_count}:{time_period}"
|
||||
for name, max_count, time_period in zip(
|
||||
task_conf.groups.name,
|
||||
task_conf.groups.max_count,
|
||||
task_conf.groups.time_period_hour,
|
||||
)
|
||||
)
|
||||
)
|
||||
res.extend(["--penalty-config", penalty_config])
|
||||
res.extend(["--group-config", overwrite_group_config_str])
|
||||
else:
|
||||
res.extend(["--group-config", group_config_str])
|
||||
return res
|
||||
|
||||
|
||||
|
@ -175,8 +100,7 @@ def get_health_check_stage(
|
|||
name="local",
|
||||
with_=result.ExecutorWith(
|
||||
default=result.Cmd(
|
||||
cpu_limit=common.Time("10s"),
|
||||
clock_limit=common.Time("20s"),
|
||||
cpu_limit=common.Time("10s"), clock_limit=common.Time("20s")
|
||||
),
|
||||
cases=[
|
||||
result.OptionalCmd(
|
||||
|
@ -184,7 +108,7 @@ def get_health_check_stage(
|
|||
),
|
||||
result.OptionalCmd(
|
||||
args=get_teapot_check_args(repo_conf, task_conf),
|
||||
env=get_teapot_env(repo_conf),
|
||||
env=[f"LOG_FILE_PATH={TEAPOT_LOG_PATH}"],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -206,3 +130,12 @@ def calc_sha256sum(file_path: Path) -> str:
|
|||
for byte_block in iter(lambda: f.read(64 * 1024), b""):
|
||||
sha256_hash.update(byte_block)
|
||||
return sha256_hash.hexdigest()
|
||||
|
||||
|
||||
def get_hashes(repo_conf: repo.Config) -> List[str]:
|
||||
base_dir = (repo_conf.root / repo_conf.path).parent
|
||||
immutable_dir = base_dir / "immutable_files"
|
||||
immutable_files = [
|
||||
immutable_dir / Path(file).name for file in repo_conf.files.immutable
|
||||
]
|
||||
return [calc_sha256sum(file) for file in immutable_files]
|
||||
|
|
|
@ -61,7 +61,7 @@ def get_parser_handler_map(
|
|||
task.Parser.CPPLINT: (fix_keyword, task_stage.cpplint),
|
||||
task.Parser.RESULT_DETAIL: (fix_result_detail, task_stage.result_detail),
|
||||
task.Parser.DUMMY: (fix_dummy, task_stage.dummy),
|
||||
task.Parser.RESULT_STATUS: (fix_result_status, task_stage.result_status),
|
||||
task.Parser.RESULT_STATUS: (fix_dummy, task_stage.result_status),
|
||||
task.Parser.FILE: (fix_file, task_stage.file),
|
||||
task.Parser.DIFF: (
|
||||
partial(
|
||||
|
@ -124,11 +124,10 @@ def fix_keyword(
|
|||
for keyword, score in zip(keyword_config.keyword, keyword_config.weight):
|
||||
score_groups.setdefault(score, []).append(keyword)
|
||||
keyword_parser.with_ = result.KeywordMatchConfig(
|
||||
score=keyword_config.score,
|
||||
matches=[
|
||||
result.KeywordConfig(keywords=keywords, score=score)
|
||||
for score, keywords in score_groups.items()
|
||||
],
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
|
@ -151,29 +150,17 @@ def fix_result_detail(
|
|||
show_memory=result_detail_parser_config.mem,
|
||||
show_error=result_detail_parser_config.error,
|
||||
show_proc_peak=result_detail_parser_config.proc_peak,
|
||||
files_in_code_block=result_detail_parser_config.code_block,
|
||||
max_file_length=result_detail_parser_config.max_length,
|
||||
)
|
||||
|
||||
|
||||
def fix_dummy(
|
||||
dummy_parser_config: task.ParserDummy, dummy_parser: result.Parser
|
||||
) -> None:
|
||||
# we don't use dummy parser in real application
|
||||
dummy_parser.with_ = result.DummyConfig(
|
||||
score=dummy_parser_config.score,
|
||||
comment=dummy_parser_config.comment,
|
||||
force_quit=dummy_parser_config.force_quit,
|
||||
)
|
||||
|
||||
|
||||
def fix_result_status(
|
||||
result_status_parser_config: task.ParserResultStatus,
|
||||
result_status_parser: result.Parser,
|
||||
) -> None:
|
||||
result_status_parser.with_ = result.ResultStatusConfig(
|
||||
score=result_status_parser_config.score,
|
||||
comment=result_status_parser_config.comment,
|
||||
force_quit_on_not_accepted=result_status_parser_config.force_quit,
|
||||
force_quit_on_not_accepted=dummy_parser_config.force_quit,
|
||||
)
|
||||
|
||||
|
||||
|
@ -228,24 +215,18 @@ def fix_diff(
|
|||
if cmd.proc_limit == executor.with_.default.proc_limit:
|
||||
cmd.proc_limit = None
|
||||
stage_cases.append(cmd)
|
||||
|
||||
def get_diff_attribute(attribute_name: str) -> Any:
|
||||
if case.diff and attribute_name in case.diff.model_fields_set:
|
||||
return getattr(case.diff, attribute_name)
|
||||
return getattr(task_stage.diff, attribute_name)
|
||||
|
||||
parser_case = result.DiffCasesConfig(
|
||||
outputs=[
|
||||
result.DiffOutputConfig(
|
||||
score=get_diff_attribute("score"),
|
||||
filename="stdout",
|
||||
score=case.diff.output.score,
|
||||
file_name="stdout",
|
||||
answer_path=stdout,
|
||||
compare_space=not get_diff_attribute("ignore_spaces"),
|
||||
always_hide=get_diff_attribute("hide"),
|
||||
force_quit_on_diff=get_diff_attribute("force_quit"),
|
||||
max_diff_length=get_diff_attribute("max_length"),
|
||||
max_diff_lines=get_diff_attribute("max_lines"),
|
||||
hide_common_prefix=get_diff_attribute("hide_common_prefix"),
|
||||
force_quit_on_diff=case.diff.output.force_quit,
|
||||
always_hide=case.diff.output.hide,
|
||||
compare_space=not case.diff.output.ignore_spaces,
|
||||
max_diff_length=case.diff.output.max_length,
|
||||
max_diff_lines=case.diff.output.max_lines,
|
||||
hide_common_prefix=case.diff.output.hide_common_prefix,
|
||||
)
|
||||
]
|
||||
)
|
||||
|
@ -253,20 +234,18 @@ def fix_diff(
|
|||
for case_name in unspecified_cases:
|
||||
cmd = result.OptionalCmd(
|
||||
stdin=result.LocalFile(src=str(base_dir / f"{case_name}.in")),
|
||||
cpu_limit=None,
|
||||
clock_limit=None,
|
||||
memory_limit=None,
|
||||
proc_limit=None,
|
||||
)
|
||||
stage_cases.append(cmd)
|
||||
parser_case = result.DiffCasesConfig(
|
||||
outputs=[
|
||||
result.DiffOutputConfig(
|
||||
score=task_stage.diff.score,
|
||||
filename="stdout",
|
||||
score=task_stage.diff.default_score,
|
||||
file_name="stdout",
|
||||
answer_path=str(base_dir / f"{case_name}.out"),
|
||||
compare_space=not task_stage.diff.ignore_spaces,
|
||||
always_hide=task_stage.diff.hide,
|
||||
force_quit_on_diff=task_stage.diff.force_quit,
|
||||
max_diff_length=task_stage.diff.max_length,
|
||||
max_diff_lines=task_stage.diff.max_lines,
|
||||
hide_common_prefix=task_stage.diff.hide_common_prefix,
|
||||
)
|
||||
]
|
||||
)
|
||||
|
|
|
@ -5,8 +5,6 @@ sandbox-token = "test"
|
|||
max-total-score = 1000
|
||||
max-size = 50.5
|
||||
|
||||
immutable_path = "immutable"
|
||||
|
||||
# for tests
|
||||
[groups]
|
||||
name = ["joj", "run"]
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "hw7 ex2",
|
||||
"logPath": "/home/tt/.cache/joj3/joj3.log",
|
||||
"expireUnixTimestamp": 0,
|
||||
"effectiveUnixTimestamp": 0,
|
||||
"expireUnixTimestamp": 1735574399,
|
||||
"effectiveUnixTimestamp": 1735487999,
|
||||
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||
"maxTotalScore": 10245871,
|
||||
"stage": {
|
||||
|
@ -64,8 +64,8 @@
|
|||
"-repoSize=50.5",
|
||||
"-meta=README.md",
|
||||
"-meta=Changelog.md",
|
||||
"-checkFileSumList=b1bbad25b830db0a77b15a033f9ca1b7ab44c1d2d05056412bd3e4421645f0bf,2ba059f3977e2e3dee6cacbfbf0ba2578baa1b8e04b4977aec400868b6e49856,3db23f7fb2ca9814617e767ddc41b77073180b3b0b73e87b5f2a6d3129f88f3a,a5b63323a692d3d8b952442969649b4f823d58dae26429494f613df160710dfc",
|
||||
"-checkFileNameList=.gitattributes,.gitea/workflows/push.yaml,.gitea/workflows/release.yaml,.gitignore"
|
||||
"-checkFileSumList=a5b63323a692d3d8b952442969649b4f823d58dae26429494f613df160710dfc,b1bbad25b830db0a77b15a033f9ca1b7ab44c1d2d05056412bd3e4421645f0bf,2ba059f3977e2e3dee6cacbfbf0ba2578baa1b8e04b4977aec400868b6e49856,3db23f7fb2ca9814617e767ddc41b77073180b3b0b73e87b5f2a6d3129f88f3a",
|
||||
"-checkFileNameList=.gitignore,.gitattributes,.gitea/workflows/push.yaml,.gitea/workflows/release.yaml"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -75,17 +75,10 @@
|
|||
"/home/tt/.config/teapot/teapot.env",
|
||||
"--grading-repo-name",
|
||||
"ece280-joj",
|
||||
"--scoreboard-filename",
|
||||
"scoreboard-hw7.csv",
|
||||
"--group-config",
|
||||
"Manuel=500:24,Boming=501:48,Nuvole=502:72",
|
||||
"--end-time",
|
||||
"2024-12-30T23:59:59",
|
||||
"--penalty-config",
|
||||
"24.0=0.5,48.0=0.25,72.0=0.1"
|
||||
"Manuel=500:24,Boming=501:48,Nuvole=502:72"
|
||||
],
|
||||
"env": [
|
||||
"REPOS_DIR=/home/tt/.cache",
|
||||
"LOG_FILE_PATH=/home/tt/.cache/joint-teapot-debug.log"
|
||||
]
|
||||
}
|
||||
|
@ -267,7 +260,6 @@
|
|||
{
|
||||
"name": "keyword",
|
||||
"with": {
|
||||
"score": 0,
|
||||
"matches": [
|
||||
{
|
||||
"keywords": [
|
||||
|
@ -376,7 +368,6 @@
|
|||
{
|
||||
"name": "clangtidy",
|
||||
"with": {
|
||||
"score": 0,
|
||||
"matches": [
|
||||
{
|
||||
"keywords": [
|
||||
|
@ -507,14 +498,12 @@
|
|||
{
|
||||
"name": "keyword",
|
||||
"with": {
|
||||
"score": 0,
|
||||
"matches": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cppcheck",
|
||||
"with": {
|
||||
"score": 0,
|
||||
"matches": [
|
||||
{
|
||||
"keywords": [
|
||||
|
@ -537,7 +526,6 @@
|
|||
{
|
||||
"name": "clangtidy",
|
||||
"with": {
|
||||
"score": 0,
|
||||
"matches": []
|
||||
}
|
||||
},
|
||||
|
@ -563,7 +551,6 @@
|
|||
{
|
||||
"name": "cpplint",
|
||||
"with": {
|
||||
"score": 0,
|
||||
"matches": []
|
||||
}
|
||||
},
|
||||
|
@ -572,7 +559,7 @@
|
|||
"with": {
|
||||
"score": 0,
|
||||
"comment": "",
|
||||
"forceQuitOnNotAccepted": true
|
||||
"forceQuitOnNotAccepted": false
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -586,7 +573,7 @@
|
|||
"with": {
|
||||
"score": 0,
|
||||
"comment": "",
|
||||
"forceQuit": false
|
||||
"forceQuitOnNotAccepted": false
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -664,7 +651,6 @@
|
|||
{
|
||||
"name": "cpplint",
|
||||
"with": {
|
||||
"score": 0,
|
||||
"matches": [
|
||||
{
|
||||
"keywords": [
|
||||
|
@ -763,27 +749,7 @@
|
|||
"dataSegmentLimit": false,
|
||||
"addressSpaceLimit": false
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"stdin": {
|
||||
"content": ""
|
||||
},
|
||||
"cpuLimit": 500000000,
|
||||
"clockLimit": 1000000000,
|
||||
"memoryLimit": 5242880
|
||||
},
|
||||
{
|
||||
"stdin": {
|
||||
"content": ""
|
||||
},
|
||||
"memoryLimit": 5242880
|
||||
},
|
||||
{
|
||||
"stdin": {
|
||||
"content": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
"cases": []
|
||||
}
|
||||
},
|
||||
"parsers": [
|
||||
|
@ -791,53 +757,7 @@
|
|||
"name": "diff",
|
||||
"with": {
|
||||
"name": "diff",
|
||||
"cases": [
|
||||
{
|
||||
"outputs": [
|
||||
{
|
||||
"score": 10,
|
||||
"filename": "stdout",
|
||||
"answerPath": "/home/tt/.config/joj/basic/cases/case0.out",
|
||||
"compareSpace": false,
|
||||
"alwaysHide": false,
|
||||
"forceQuitOnDiff": false,
|
||||
"maxDiffLength": 2048,
|
||||
"maxDiffLines": 50,
|
||||
"hideCommonPrefix": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"outputs": [
|
||||
{
|
||||
"score": 5,
|
||||
"filename": "stdout",
|
||||
"answerPath": "/home/tt/.config/joj/basic/cases/case1.out",
|
||||
"compareSpace": false,
|
||||
"alwaysHide": false,
|
||||
"forceQuitOnDiff": false,
|
||||
"maxDiffLength": 2048,
|
||||
"maxDiffLines": 50,
|
||||
"hideCommonPrefix": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"outputs": [
|
||||
{
|
||||
"score": 10,
|
||||
"filename": "stdout",
|
||||
"answerPath": "/home/tt/.config/joj/basic/cases/case2.out",
|
||||
"compareSpace": false,
|
||||
"alwaysHide": true,
|
||||
"forceQuitOnDiff": false,
|
||||
"maxDiffLength": 2048,
|
||||
"maxDiffLines": 50,
|
||||
"hideCommonPrefix": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
"cases": []
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -878,20 +798,9 @@
|
|||
"--grading-repo-name",
|
||||
"ece280-joj",
|
||||
"--max-total-score",
|
||||
"10245871",
|
||||
"--issue-label-name",
|
||||
"Kind/Testing",
|
||||
"--issue-label-color",
|
||||
"#795548",
|
||||
"--scoreboard-filename",
|
||||
"scoreboard-hw7.csv",
|
||||
"--end-time",
|
||||
"2024-12-30T23:59:59",
|
||||
"--penalty-config",
|
||||
"24.0=0.5,48.0=0.25,72.0=0.1"
|
||||
"10245871"
|
||||
],
|
||||
"env": [
|
||||
"REPOS_DIR=/home/tt/.cache",
|
||||
"LOG_FILE_PATH=/home/tt/.cache/joint-teapot-debug.log"
|
||||
],
|
||||
"stdin": {
|
||||
|
|
|
@ -2,13 +2,8 @@
|
|||
task.name = "hw7 ex2" # task name
|
||||
|
||||
max-total-score = 10245871
|
||||
time.end = 2024-12-30 23:59:59+08:00
|
||||
release.end-time = 2024-12-30 23:59:59+08:00
|
||||
release.begin-time = 2024-12-29 23:59:59+08:00
|
||||
scoreboard = "auto"
|
||||
|
||||
[penalties]
|
||||
hours = [ 24, 48, 72 ]
|
||||
factors = [ 0.5, 0.25, 0.1 ]
|
||||
|
||||
[groups]
|
||||
name = ["Manuel", "Boming", "Nuvole"]
|
||||
|
@ -92,26 +87,23 @@ copy-in-cwd = false
|
|||
files.import = [ "h7/build/ex2-asan" ]
|
||||
limit.mem = "128m"
|
||||
|
||||
diff.score = 10
|
||||
|
||||
parsers = [ "diff", "result-detail" ]
|
||||
result-detail.exit-status = true
|
||||
result-detail.stderr = true
|
||||
|
||||
# will be removed as long as the name is fixed
|
||||
case0.diff.output.score = 5
|
||||
case0.limit.cpu = "0.5s"
|
||||
case0.limit.mem = "5m"
|
||||
case0.diff.ignore-spaces = true
|
||||
case0.diff.output.ignore-spaces = true
|
||||
#case0.limit.stdout = 8
|
||||
#case0.command = "./h7/build/ex2"
|
||||
case0.in = "case0.in"
|
||||
|
||||
case1.diff.score = 5
|
||||
case1.diff.output.score = 5
|
||||
case1.limit.cpu = "1s"
|
||||
case1.limit.mem = "5m"
|
||||
case1.diff.ignore-spaces = true
|
||||
case1.diff.output.ignore-spaces = true
|
||||
#case1.limit.stdout = 8
|
||||
#case1.command = "./h7/build/ex2"
|
||||
case1.in = "case1.in"
|
||||
|
||||
case2.diff.hide = true
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "hw7 ex2",
|
||||
"logPath": "/home/tt/.cache/joj3/joj3.log",
|
||||
"expireUnixTimestamp": 0,
|
||||
"effectiveUnixTimestamp": 0,
|
||||
"expireUnixTimestamp": 1735574399,
|
||||
"effectiveUnixTimestamp": 1735487999,
|
||||
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||
"maxTotalScore": 100,
|
||||
"stage": {
|
||||
|
@ -78,7 +78,6 @@
|
|||
{
|
||||
"name": "clangtidy",
|
||||
"with": {
|
||||
"score": 0,
|
||||
"matches": [
|
||||
{
|
||||
"keywords": [
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# general task configuration
|
||||
task.name = "hw7 ex2" # task name
|
||||
|
||||
time.end = 2024-12-30 23:59:59+08:00
|
||||
release.end-time = 2024-12-30 23:59:59+08:00
|
||||
release.begin-time = 2024-12-29 23:59:59+08:00
|
||||
|
||||
[[stages]]
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "hw7 ex2",
|
||||
"logPath": "/home/tt/.cache/joj3/joj3.log",
|
||||
"expireUnixTimestamp": 0,
|
||||
"effectiveUnixTimestamp": 0,
|
||||
"expireUnixTimestamp": 1735574399,
|
||||
"effectiveUnixTimestamp": 1735487999,
|
||||
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||
"maxTotalScore": 100,
|
||||
"stage": {
|
||||
|
@ -71,7 +71,6 @@
|
|||
{
|
||||
"name": "cppcheck",
|
||||
"with": {
|
||||
"score": 0,
|
||||
"matches": [
|
||||
{
|
||||
"keywords": [
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# general task configuration
|
||||
task.name = "hw7 ex2" # task name
|
||||
|
||||
time.end = 2024-12-30 23:59:59+08:00
|
||||
time.begin = 2024-12-29 23:59:59+08:00
|
||||
release.end-time = 2024-12-30 23:59:59+08:00
|
||||
release.begin-time = 2024-12-29 23:59:59+08:00
|
||||
|
||||
[[stages]]
|
||||
name = "[cq] Cppcheck"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "hw7 ex2",
|
||||
"logPath": "/home/tt/.cache/joj3/joj3.log",
|
||||
"expireUnixTimestamp": 0,
|
||||
"effectiveUnixTimestamp": 0,
|
||||
"expireUnixTimestamp": 1735574399,
|
||||
"effectiveUnixTimestamp": 1735487999,
|
||||
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||
"maxTotalScore": 100,
|
||||
"stage": {
|
||||
|
@ -70,7 +70,6 @@
|
|||
{
|
||||
"name": "cpplint",
|
||||
"with": {
|
||||
"score": 0,
|
||||
"matches": [
|
||||
{
|
||||
"keywords": [
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# general task configuration
|
||||
task.name = "hw7 ex2" # task name
|
||||
|
||||
time.end = 2024-12-30 23:59:59+08:00
|
||||
release.end-time = 2024-12-30 23:59:59+08:00
|
||||
release.begin-time = 2024-12-29 23:59:59+08:00
|
||||
|
||||
[[stages]]
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "hw7 ex2",
|
||||
"logPath": "/home/tt/.cache/joj3/joj3.log",
|
||||
"expireUnixTimestamp": 0,
|
||||
"effectiveUnixTimestamp": 0,
|
||||
"expireUnixTimestamp": 1735574399,
|
||||
"effectiveUnixTimestamp": 1735487999,
|
||||
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||
"maxTotalScore": 100,
|
||||
"stage": {
|
||||
|
@ -144,7 +144,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"score": 5,
|
||||
"filename": "stdout",
|
||||
"fileName": "stdout",
|
||||
"answerPath": "/home/tt/.config/joj/diff/case0.out",
|
||||
"compareSpace": false,
|
||||
"alwaysHide": false,
|
||||
|
@ -159,7 +159,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"score": 123214122421,
|
||||
"filename": "stdout",
|
||||
"fileName": "stdout",
|
||||
"answerPath": "/home/tt/.config/joj/diff/case1.out",
|
||||
"compareSpace": false,
|
||||
"alwaysHide": false,
|
||||
|
@ -174,7 +174,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"score": 1232131,
|
||||
"filename": "stdout",
|
||||
"fileName": "stdout",
|
||||
"answerPath": "/home/tt/.config/joj/diff/case9.out",
|
||||
"compareSpace": false,
|
||||
"alwaysHide": false,
|
||||
|
@ -189,7 +189,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"score": 92321,
|
||||
"filename": "stdout",
|
||||
"fileName": "stdout",
|
||||
"answerPath": "/home/tt/.config/joj/diff/task1/subtask1/case11.out",
|
||||
"compareSpace": false,
|
||||
"alwaysHide": false,
|
||||
|
@ -204,7 +204,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"score": 823131,
|
||||
"filename": "stdout",
|
||||
"fileName": "stdout",
|
||||
"answerPath": "/home/tt/.config/joj/diff/task1/subtask1/case10.out",
|
||||
"compareSpace": false,
|
||||
"alwaysHide": false,
|
||||
|
@ -219,7 +219,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"score": 2590,
|
||||
"filename": "stdout",
|
||||
"fileName": "stdout",
|
||||
"answerPath": "/home/tt/.config/joj/diff/task1/case5.out",
|
||||
"compareSpace": false,
|
||||
"alwaysHide": false,
|
||||
|
@ -234,7 +234,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"score": 100,
|
||||
"filename": "stdout",
|
||||
"fileName": "stdout",
|
||||
"answerPath": "/home/tt/.config/joj/diff/case2.out",
|
||||
"compareSpace": false,
|
||||
"alwaysHide": false,
|
||||
|
@ -249,7 +249,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"score": 100,
|
||||
"filename": "stdout",
|
||||
"fileName": "stdout",
|
||||
"answerPath": "/home/tt/.config/joj/diff/task1/case4.out",
|
||||
"compareSpace": false,
|
||||
"alwaysHide": false,
|
||||
|
@ -264,7 +264,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"score": 100,
|
||||
"filename": "stdout",
|
||||
"fileName": "stdout",
|
||||
"answerPath": "/home/tt/.config/joj/diff/task2/case6.out",
|
||||
"compareSpace": false,
|
||||
"alwaysHide": false,
|
||||
|
@ -279,7 +279,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"score": 100,
|
||||
"filename": "stdout",
|
||||
"fileName": "stdout",
|
||||
"answerPath": "/home/tt/.config/joj/diff/task2/case7.out",
|
||||
"compareSpace": false,
|
||||
"alwaysHide": false,
|
||||
|
@ -294,7 +294,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"score": 100,
|
||||
"filename": "stdout",
|
||||
"fileName": "stdout",
|
||||
"answerPath": "/home/tt/.config/joj/diff/task2/case8.out",
|
||||
"compareSpace": false,
|
||||
"alwaysHide": false,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# general task configuration
|
||||
task.name = "hw7 ex2" # task name
|
||||
|
||||
time.end = 2024-12-30 23:59:59+08:00
|
||||
release.end-time = 2024-12-30 23:59:59+08:00
|
||||
release.begin-time = 2024-12-29 23:59:59+08:00
|
||||
|
||||
[[stages]]
|
||||
|
@ -17,26 +17,26 @@ parsers = [ "diff", "result-detail" ]
|
|||
result-detail.exit-status = true
|
||||
result-detail.stderr = true
|
||||
|
||||
diff.score = 100
|
||||
diff.default-score = 100
|
||||
|
||||
case0.diff.score = 5
|
||||
case0.diff.output.score = 5
|
||||
case0.limit.cpu = "1s"
|
||||
case0.limit.mem = "2m"
|
||||
case0.diff.ignore-spaces = true
|
||||
case0.diff.output.ignore-spaces = true
|
||||
case0.command = "./h7/build/ex2"
|
||||
case0.in = "case0.in"
|
||||
|
||||
case1.diff.score = 123214122421
|
||||
case1.diff.output.score = 123214122421
|
||||
case1.limit.cpu = "2s"
|
||||
case1.limit.mem = "4m"
|
||||
case1.diff.ignore-spaces = true
|
||||
case1.diff.output.ignore-spaces = true
|
||||
case1.command = "./h7/build/ex2"
|
||||
|
||||
case9.diff.score = 1232131
|
||||
case9.diff.output.score = 1232131
|
||||
case9.limit.mem = "10m"
|
||||
|
||||
case11.diff.score = 92321
|
||||
case11.diff.output.score = 92321
|
||||
|
||||
case10.diff.score = 823131
|
||||
case10.diff.output.score = 823131
|
||||
|
||||
case5.diff.score = 2590
|
||||
case5.diff.output.score = 2590
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "hw7 ex2",
|
||||
"logPath": "/home/tt/.cache/joj3/joj3.log",
|
||||
"expireUnixTimestamp": 0,
|
||||
"effectiveUnixTimestamp": 0,
|
||||
"expireUnixTimestamp": 1735574399,
|
||||
"effectiveUnixTimestamp": 1735487999,
|
||||
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||
"maxTotalScore": 100,
|
||||
"stage": {
|
||||
|
@ -74,7 +74,6 @@
|
|||
{
|
||||
"name": "elf",
|
||||
"with": {
|
||||
"score": 0,
|
||||
"matches": [
|
||||
{
|
||||
"keywords": [
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# general task configuration
|
||||
task.name = "hw7 ex2" # task name
|
||||
|
||||
time.end = 2024-12-30 23:59:59+08:00
|
||||
release.end-time = 2024-12-30 23:59:59+08:00
|
||||
release.begin-time = 2024-12-29 23:59:59+08:00
|
||||
|
||||
[[stages]]
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "hw7 ex2",
|
||||
"logPath": "/home/tt/.cache/joj3/joj3.log",
|
||||
"expireUnixTimestamp": 0,
|
||||
"effectiveUnixTimestamp": 0,
|
||||
"expireUnixTimestamp": 1735574399,
|
||||
"effectiveUnixTimestamp": 1735487999,
|
||||
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||
"maxTotalScore": 100,
|
||||
"stage": {
|
||||
|
@ -73,7 +73,6 @@
|
|||
{
|
||||
"name": "keyword",
|
||||
"with": {
|
||||
"score": 0,
|
||||
"matches": [
|
||||
{
|
||||
"keywords": [
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# general task configuration
|
||||
task.name = "hw7 ex2" # task name
|
||||
|
||||
time.end = 2024-12-30 23:59:59+08:00
|
||||
release.end-time = 2024-12-30 23:59:59+08:00
|
||||
release.begin-time = 2024-12-29 23:59:59+08:00
|
||||
|
||||
[[stages]]
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "hw7 ex2",
|
||||
"logPath": "/home/tt/.cache/joj3/joj3.log",
|
||||
"expireUnixTimestamp": 0,
|
||||
"effectiveUnixTimestamp": 0,
|
||||
"expireUnixTimestamp": 1735574399,
|
||||
"effectiveUnixTimestamp": 1735487999,
|
||||
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||
"maxTotalScore": 100,
|
||||
"stage": {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# general task configuration
|
||||
task.name = "hw7 ex2" # task name
|
||||
|
||||
time.end = 2024-12-30 23:59:59+08:00
|
||||
release.end-time = 2024-12-30 23:59:59+08:00
|
||||
release.begin-time = 2024-12-29 23:59:59+08:00
|
||||
|
||||
[[stages]]
|
||||
|
|
Loading…
Reference in New Issue
Block a user