Compare commits

...

10 Commits

Author SHA1 Message Date
dd6955fd7e fix: log path
Some checks failed
build / build (push) Failing after 1m47s
2025-05-25 16:28:47 +08:00
c3f2b21732
fix: default limit
All checks were successful
build / build (push) Successful in 1m42s
build / build (pull_request) Successful in 2m2s
2025-05-22 20:46:01 -04:00
dcebf86408 fix: remove none stdin for diff
All checks were successful
build / build (push) Successful in 13m50s
build / build (pull_request) Successful in 14m0s
2025-05-22 16:06:03 +08:00
183e6f1545 feat: add DEFAULT_PROC_LIMIT n DEFAULT_CLOCK_LIMIT_MULTIPLIER
All checks were successful
build / build (push) Successful in 1m32s
build / build (pull_request) Successful in 1m40s
2025-05-22 15:27:50 +08:00
b4a9d0cb62 fix: add back DEFAULT_CASE_SCORE
All checks were successful
build / build (pull_request) Successful in 1m33s
build / build (push) Successful in 1m42s
2025-05-22 15:18:49 +08:00
68fedcfe95 fix: conflict files
All checks were successful
build / build (pull_request) Successful in 1m48s
build / build (push) Successful in 1m45s
2025-05-22 15:03:34 +08:00
927e5ce95d fix: cases specific numerics remove when unecessary
All checks were successful
build / build (push) Successful in 1m43s
build / build (pull_request) Successful in 1m22s
2025-05-22 14:59:50 +08:00
ca63a94238 feat: add default score for diff
All checks were successful
build / build (push) Successful in 1m54s
2025-05-22 14:28:35 +08:00
5acb2ca201 fix: remove stdin for diff stage
All checks were successful
build / build (push) Successful in 2m1s
2025-05-22 14:08:39 +08:00
6375a37069 fix(diff): bugs in auto detect cases (#14)
All checks were successful
build / build (push) Successful in 2m5s
- fix original logic issue of cases generation (originally there is duplication on cases, e.g. `case5`, `task1/case5`)
- fix the issue that without any specification there is no cases input and output in `diff` stage

Co-authored-by: Boming Zhang <bomingzh@sjtu.edu.cn>
Reviewed-on: #14
Reviewed-by: 张泊明518370910136 <bomingzh@sjtu.edu.cn>
Co-authored-by: jon-lee <jon-lee@sjtu.edu.cn>
Co-committed-by: jon-lee <jon-lee@sjtu.edu.cn>
2025-05-22 01:34:01 +08:00
7 changed files with 107 additions and 32 deletions

View File

@ -6,10 +6,12 @@ DEFAULT_CPU_LIMIT = Time("1s")
DEFAULT_MEMORY_LIMIT = Memory("256m") DEFAULT_MEMORY_LIMIT = Memory("256m")
DEFAULT_FILE_LIMIT = Memory("32m") DEFAULT_FILE_LIMIT = Memory("32m")
DEFAULT_CASE_SCORE = 5 DEFAULT_CASE_SCORE = 5
DEFAULT_CLOCK_LIMIT_MULTIPLIER = 2
DEFAULT_PROC_LIMIT = 50
JOJ3_CONFIG_ROOT = Path("/home/tt/.config/joj") JOJ3_CONFIG_ROOT = Path("/home/tt/.config/joj")
TEAPOT_CONFIG_ROOT = Path("/home/tt/.config/teapot") TEAPOT_CONFIG_ROOT = Path("/home/tt/.config/teapot")
CACHE_ROOT = Path("/home/tt/.cache") CACHE_ROOT = Path("/home/tt/.cache")
JOJ3_LOG_PATH = CACHE_ROOT / "joj3.log" JOJ3_LOG_PATH = CACHE_ROOT / "joj3/joj3.log"
TEAPOT_LOG_PATH = CACHE_ROOT / "joint-teapot-debug.log" TEAPOT_LOG_PATH = CACHE_ROOT / "joint-teapot-debug.log"
ACTOR_CSV_PATH = JOJ3_CONFIG_ROOT / "students.csv" ACTOR_CSV_PATH = JOJ3_CONFIG_ROOT / "students.csv"

View File

@ -3,9 +3,11 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
from pydantic import BaseModel, ConfigDict, Field, field_validator from pydantic import BaseModel, ConfigDict, Field, field_validator
from joj3_config_generator.models.const import ( from joj3_config_generator.models.const import (
DEFAULT_CLOCK_LIMIT_MULTIPLIER,
DEFAULT_CPU_LIMIT, DEFAULT_CPU_LIMIT,
DEFAULT_FILE_LIMIT, DEFAULT_FILE_LIMIT,
DEFAULT_MEMORY_LIMIT, DEFAULT_MEMORY_LIMIT,
DEFAULT_PROC_LIMIT,
) )
@ -49,10 +51,13 @@ class Cmd(BaseModel):
stdout: Union[Collector, StreamOut] = Collector(name="stdout") stdout: Union[Collector, StreamOut] = Collector(name="stdout")
stderr: Union[Collector, StreamOut] = Collector(name="stderr") stderr: Union[Collector, StreamOut] = Collector(name="stderr")
cpu_limit: int = Field(DEFAULT_CPU_LIMIT, serialization_alias="cpuLimit") cpu_limit: int = Field(DEFAULT_CPU_LIMIT, serialization_alias="cpuLimit")
clock_limit: int = Field(2 * DEFAULT_CPU_LIMIT, serialization_alias="clockLimit") clock_limit: int = Field(
DEFAULT_CLOCK_LIMIT_MULTIPLIER * DEFAULT_CPU_LIMIT,
serialization_alias="clockLimit",
)
memory_limit: int = Field(DEFAULT_MEMORY_LIMIT, serialization_alias="memoryLimit") memory_limit: int = Field(DEFAULT_MEMORY_LIMIT, serialization_alias="memoryLimit")
stack_limit: int = Field(0, serialization_alias="stackLimit") stack_limit: int = Field(0, serialization_alias="stackLimit")
proc_limit: int = Field(50, serialization_alias="procLimit") proc_limit: int = Field(DEFAULT_PROC_LIMIT, serialization_alias="procLimit")
cpu_rate_limit: int = Field(0, serialization_alias="cpuRateLimit") cpu_rate_limit: int = Field(0, serialization_alias="cpuRateLimit")
cpu_set_limit: str = Field("", serialization_alias="cpuSetLimit") cpu_set_limit: str = Field("", serialization_alias="cpuSetLimit")
copy_in: Dict[str, InputFile] = Field({}, serialization_alias="copyIn") copy_in: Dict[str, InputFile] = Field({}, serialization_alias="copyIn")

View File

@ -7,6 +7,7 @@ from pydantic import BaseModel, ConfigDict, Field, field_validator, model_valida
from joj3_config_generator.models.common import Memory, Time from joj3_config_generator.models.common import Memory, Time
from joj3_config_generator.models.const import ( from joj3_config_generator.models.const import (
DEFAULT_CASE_SCORE,
DEFAULT_CPU_LIMIT, DEFAULT_CPU_LIMIT,
DEFAULT_FILE_LIMIT, DEFAULT_FILE_LIMIT,
DEFAULT_MEMORY_LIMIT, DEFAULT_MEMORY_LIMIT,
@ -51,6 +52,7 @@ class Outputs(BaseModel):
class ParserDiff(BaseModel): class ParserDiff(BaseModel):
output: Outputs = Outputs() output: Outputs = Outputs()
default_score: int = DEFAULT_CASE_SCORE
class Files(BaseModel): class Files(BaseModel):
@ -125,9 +127,14 @@ class Stage(BaseModel):
@classmethod @classmethod
def gather_cases(cls: Type["Stage"], values: Dict[str, Any]) -> Dict[str, Any]: def gather_cases(cls: Type["Stage"], values: Dict[str, Any]) -> Dict[str, Any]:
cases = {k: v for k, v in values.items() if k.startswith("case")} cases = {k: v for k, v in values.items() if k.startswith("case")}
for key in cases: limit = values.get("limit", {})
parsed_cases = {}
for key, case in cases.items():
case_with_limit = {**limit, **case.get("limit", {})}
case_for_parsing = {**case, "limit": case_with_limit}
parsed_cases[key] = case_for_parsing
values.pop(key) values.pop(key)
values["cases"] = {k: v for k, v in cases.items()} values["cases"] = parsed_cases
return values return values

View File

@ -4,9 +4,13 @@ from functools import partial
from pathlib import Path from pathlib import Path
from typing import Any, Callable, Dict, List, Set, Tuple from typing import Any, Callable, Dict, List, Set, Tuple
from joj3_config_generator.models import const, result, task from joj3_config_generator.models import result, task
from joj3_config_generator.models.common import Memory, Time from joj3_config_generator.models.common import Memory, Time
from joj3_config_generator.models.const import JOJ3_CONFIG_ROOT from joj3_config_generator.models.const import (
DEFAULT_CLOCK_LIMIT_MULTIPLIER,
DEFAULT_PROC_LIMIT,
JOJ3_CONFIG_ROOT,
)
from joj3_config_generator.models.task import Parser as ParserEnum from joj3_config_generator.models.task import Parser as ParserEnum
@ -194,9 +198,9 @@ def fix_diff(
), ),
args=shlex.split(case_stage.command) if case_stage.command else None, args=shlex.split(case_stage.command) if case_stage.command else None,
cpu_limit=case_stage.limit.cpu, cpu_limit=case_stage.limit.cpu,
clock_limit=2 * case_stage.limit.cpu, clock_limit=DEFAULT_CLOCK_LIMIT_MULTIPLIER * case_stage.limit.cpu,
memory_limit=case_stage.limit.mem, memory_limit=case_stage.limit.mem,
proc_limit=50, proc_limit=DEFAULT_PROC_LIMIT,
) )
if cmd.args == executor.with_.default.args: if cmd.args == executor.with_.default.args:
cmd.args = None cmd.args = None
@ -224,13 +228,17 @@ def fix_diff(
parser_cases.append(parser_case) parser_cases.append(parser_case)
for case in default_cases: for case in default_cases:
cmd = result.OptionalCmd( cmd = result.OptionalCmd(
stdin=result.LocalFile(src=str(base_dir / f"{case}.in")) stdin=result.LocalFile(src=str(base_dir / f"{case}.in")),
cpu_limit=None,
clock_limit=None,
memory_limit=None,
proc_limit=None,
) )
stage_cases.append(cmd) stage_cases.append(cmd)
parser_case = result.DiffCasesConfig( parser_case = result.DiffCasesConfig(
outputs=[ outputs=[
result.DiffOutputConfig( result.DiffOutputConfig(
score=const.DEFAULT_CASE_SCORE, score=task_stage.diff.default_score,
file_name="stdout", file_name="stdout",
answer_path=str(base_dir / f"{case}.out"), answer_path=str(base_dir / f"{case}.out"),
) )

50
plot.py Normal file
View File

@ -0,0 +1,50 @@
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
# 加载Iris数据集并计算平均值
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['Species'] = [iris.target_names[t] for t in iris.target]
df_mean = df.groupby('Species').mean().reset_index()
# 数据整理为长格式
df_melt = df_mean.melt(id_vars='Species', var_name='Measurement', value_name='Average')
# 设置可视化参数
measurements = ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
species = df_mean['Species'].tolist()
colors = ['#4e79a7', '#f28e2b', '#e15759'] # 专业色盲友好配色
bar_width = 0.25
# 创建画布
plt.figure(figsize=(14, 8), dpi=100)
x = range(len(measurements))
# 绘制分组柱状图
for i, specie in enumerate(species):
offsets = [val + bar_width*i for val in x]
values = df_melt[df_melt['Species'] == specie]['Average']
plt.bar(offsets, values, width=bar_width, color=colors[i], label=specie, edgecolor='white', linewidth=0.5)
# 添加数据标签
for i in range(len(measurements)):
for j, specie in enumerate(species):
value = df_mean.loc[j, measurements[i]]
plt.text(x[i] + bar_width*j, value + 0.05, f'{value:.1f}',
ha='center', va='bottom', fontsize=9)
# 图表装饰
plt.title('Average Sepal and Petal Dimensions by Iris Species', pad=20, fontsize=14, fontweight='bold')
plt.xlabel('Measurement', labelpad=15, fontsize=12)
plt.ylabel('Average Dimension (cm)', labelpad=15, fontsize=12)
plt.xticks([r + bar_width for r in range(len(measurements))],
[m.replace(' (cm)', '').title() for m in measurements],
rotation=45, ha='right')
plt.ylim(0, df_melt['Average'].max()*1.3)
plt.grid(axis='y', linestyle='--', alpha=0.4)
plt.legend(title='Species', bbox_to_anchor=(1.02, 1), loc='upper left')
# 优化布局
plt.tight_layout()
plt.show()

View File

@ -29,17 +29,17 @@
}, },
"stdout": { "stdout": {
"name": "stdout", "name": "stdout",
"max": 33554432, "max": 10485760,
"pipe": true "pipe": true
}, },
"stderr": { "stderr": {
"name": "stderr", "name": "stderr",
"max": 33554432, "max": 10485760,
"pipe": true "pipe": true
}, },
"cpuLimit": 1000000000, "cpuLimit": 3000000000,
"clockLimit": 2000000000, "clockLimit": 6000000000,
"memoryLimit": 68157440, "memoryLimit": 10485760,
"stackLimit": 0, "stackLimit": 0,
"procLimit": 50, "procLimit": 50,
"cpuRateLimit": 0, "cpuRateLimit": 0,
@ -71,6 +71,8 @@
"stdin": { "stdin": {
"src": "/home/tt/.config/joj/diff/case0.in" "src": "/home/tt/.config/joj/diff/case0.in"
}, },
"cpuLimit": 1000000000,
"clockLimit": 2000000000,
"memoryLimit": 2097152 "memoryLimit": 2097152
}, },
{ {
@ -87,26 +89,22 @@
{ {
"stdin": { "stdin": {
"src": "/home/tt/.config/joj/diff/case9.in" "src": "/home/tt/.config/joj/diff/case9.in"
}, }
"memoryLimit": 268435456
}, },
{ {
"stdin": { "stdin": {
"src": "/home/tt/.config/joj/diff/task1/subtask1/case11.in" "src": "/home/tt/.config/joj/diff/task1/subtask1/case11.in"
}, }
"memoryLimit": 268435456
}, },
{ {
"stdin": { "stdin": {
"src": "/home/tt/.config/joj/diff/task1/subtask1/case10.in" "src": "/home/tt/.config/joj/diff/task1/subtask1/case10.in"
}, }
"memoryLimit": 268435456
}, },
{ {
"stdin": { "stdin": {
"src": "/home/tt/.config/joj/diff/task1/case5.in" "src": "/home/tt/.config/joj/diff/task1/case5.in"
}, }
"memoryLimit": 268435456
}, },
{ {
"stdin": { "stdin": {
@ -222,7 +220,7 @@
{ {
"outputs": [ "outputs": [
{ {
"score": 5, "score": 100,
"fileName": "stdout", "fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/case2.out", "answerPath": "/home/tt/.config/joj/diff/case2.out",
"forceQuitOnDiff": false, "forceQuitOnDiff": false,
@ -234,7 +232,7 @@
{ {
"outputs": [ "outputs": [
{ {
"score": 5, "score": 100,
"fileName": "stdout", "fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/case3.out", "answerPath": "/home/tt/.config/joj/diff/case3.out",
"forceQuitOnDiff": false, "forceQuitOnDiff": false,
@ -246,7 +244,7 @@
{ {
"outputs": [ "outputs": [
{ {
"score": 5, "score": 100,
"fileName": "stdout", "fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/task1/case4.out", "answerPath": "/home/tt/.config/joj/diff/task1/case4.out",
"forceQuitOnDiff": false, "forceQuitOnDiff": false,
@ -258,7 +256,7 @@
{ {
"outputs": [ "outputs": [
{ {
"score": 5, "score": 100,
"fileName": "stdout", "fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/task2/case6.out", "answerPath": "/home/tt/.config/joj/diff/task2/case6.out",
"forceQuitOnDiff": false, "forceQuitOnDiff": false,
@ -270,7 +268,7 @@
{ {
"outputs": [ "outputs": [
{ {
"score": 5, "score": 100,
"fileName": "stdout", "fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/task2/case7.out", "answerPath": "/home/tt/.config/joj/diff/task2/case7.out",
"forceQuitOnDiff": false, "forceQuitOnDiff": false,
@ -282,7 +280,7 @@
{ {
"outputs": [ "outputs": [
{ {
"score": 5, "score": 100,
"fileName": "stdout", "fileName": "stdout",
"answerPath": "/home/tt/.config/joj/diff/task2/case8.out", "answerPath": "/home/tt/.config/joj/diff/task2/case8.out",
"forceQuitOnDiff": false, "forceQuitOnDiff": false,

View File

@ -8,13 +8,17 @@ release.begin_time = 2024-12-29 23:59:59+08:00
name = "[joj] ex2-asan" name = "[joj] ex2-asan"
command="./h7/build/ex2-asan -a" command="./h7/build/ex2-asan -a"
files.import = [ "h7/build/ex2-asan" ] files.import = [ "h7/build/ex2-asan" ]
limit.mem = "65m" limit.cpu = "3s"
limit.mem = "10m"
limit.stdout = "10m"
limit.stderr = "10m"
parsers = [ "diff", "result-detail" ] parsers = [ "diff", "result-detail" ]
result-detail.exitstatus = true result-detail.exitstatus = true
result-detail.stderr = true result-detail.stderr = true
# will be removed as long as the name is fixed diff.default_score = 100
case0.diff.output.score = 5 case0.diff.output.score = 5
case0.limit.cpu = "1s" case0.limit.cpu = "1s"
case0.limit.mem = "2m" case0.limit.mem = "2m"
@ -29,6 +33,7 @@ case1.diff.output.ignore_spaces = true
case1.command = "./h7/build/ex2" case1.command = "./h7/build/ex2"
case9.diff.output.score = 1232131 case9.diff.output.score = 1232131
case9.limit.mem = "10m"
case11.diff.output.score = 92321 case11.diff.output.score = 92321