feat: finish keyword related
This commit is contained in:
		
							parent
							
								
									805a79bf10
								
							
						
					
					
						commit
						43b55f77ce
					
				|  | @ -1,4 +1,5 @@ | ||||||
| from joj3_config_generator.lib.repo import getHealthcheckConfig, getTeapotConfig | from joj3_config_generator.lib.repo import getHealthcheckConfig, getTeapotConfig | ||||||
|  | from joj3_config_generator.lib.task import fix_keyword | ||||||
| from joj3_config_generator.models import ( | from joj3_config_generator.models import ( | ||||||
|     Cmd, |     Cmd, | ||||||
|     CmdFile, |     CmdFile, | ||||||
|  | @ -17,7 +18,8 @@ from joj3_config_generator.models import ( | ||||||
| # FIXME: LLM generated convert function, only for demostration | # FIXME: LLM generated convert function, only for demostration | ||||||
| def convert(repo_conf: repo.Config, task_conf: task.Config) -> result.Config: | def convert(repo_conf: repo.Config, task_conf: task.Config) -> result.Config: | ||||||
|     # Create the base ResultConf object |     # Create the base ResultConf object | ||||||
|     result_conf = result.Config( |     # FIXME: wrap things in functions | ||||||
|  |     result_conf = ResultConfig( | ||||||
|         name=task_conf.task, |         name=task_conf.task, | ||||||
|         # TODO: specify the exact folder difference |         # TODO: specify the exact folder difference | ||||||
|         log_path=f"{task_conf.task.replace(' ', '-')}.log", |         log_path=f"{task_conf.task.replace(' ', '-')}.log", | ||||||
|  | @ -80,6 +82,7 @@ def convert(repo_conf: repo.Config, task_conf: task.Config) -> result.Config: | ||||||
|                 ParserConfig(name=parser, with_={}) for parser in task_stage.parsers |                 ParserConfig(name=parser, with_={}) for parser in task_stage.parsers | ||||||
|             ], |             ], | ||||||
|         ) |         ) | ||||||
|  |         # TODO: fix all parser here | ||||||
|         if "result-detail" in task_stage.parsers: |         if "result-detail" in task_stage.parsers: | ||||||
|             result_detail_parser = next( |             result_detail_parser = next( | ||||||
|                 p for p in conf_stage.parsers if p.name == "result-detail" |                 p for p in conf_stage.parsers if p.name == "result-detail" | ||||||
|  | @ -87,6 +90,20 @@ def convert(repo_conf: repo.Config, task_conf: task.Config) -> result.Config: | ||||||
|             if task_stage.result_detail is not None: |             if task_stage.result_detail is not None: | ||||||
|                 result_detail_parser.with_.update(task_stage.result_detail) |                 result_detail_parser.with_.update(task_stage.result_detail) | ||||||
| 
 | 
 | ||||||
|  |         if "dummy" in task_stage.parsers: | ||||||
|  |             dummy_parser = next(p for p in conf_stage.parsers if p.name == "dummy") | ||||||
|  |             if task_stage.dummy is not None: | ||||||
|  |                 dummy_parser.with_.update(task_stage.dummy) | ||||||
|  | 
 | ||||||
|  |         if "result-status" in task_stage.parsers: | ||||||
|  |             result_status_parser = next( | ||||||
|  |                 p for p in conf_stage.parsers if p.name == "result-status" | ||||||
|  |             ) | ||||||
|  |             if task_stage.result_status is not None: | ||||||
|  |                 result_status_parser.with_.update(task_stage.result_status) | ||||||
|  | 
 | ||||||
|  |         conf_stage = fix_keyword(task_stage, conf_stage) | ||||||
|  | 
 | ||||||
|         result_conf.stage.stages.append(conf_stage) |         result_conf.stage.stages.append(conf_stage) | ||||||
| 
 | 
 | ||||||
|     return result_conf |     return result_conf | ||||||
|  |  | ||||||
|  | @ -1,254 +1,20 @@ | ||||||
| from typing import Tuple | from joj3_config_generator.models.result import Stage as ResultStage | ||||||
| 
 | from joj3_config_generator.models.task import Stage as TaskStage | ||||||
| import rtoml |  | ||||||
| 
 |  | ||||||
| from joj3_config_generator.models import joj1, repo, result, task |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def get_conf_stage( | def fix_keyword(task_stage: TaskStage, conf_stage: ResultStage) -> ResultStage: | ||||||
|     task_stage: task.Stage, executor_with_config: result.ExecutorWith |  | ||||||
| ) -> result.StageDetail: |  | ||||||
|     conf_stage = result.StageDetail( |  | ||||||
|         name=task_stage.name if task_stage.name is not None else "", |  | ||||||
|         # TODO: we may have cq in future |  | ||||||
|         group=( |  | ||||||
|             "joj" |  | ||||||
|             if (task_stage.name is not None) and ("judge" in task_stage.name) |  | ||||||
|             else None |  | ||||||
|         ), |  | ||||||
|         executor=result.Executor( |  | ||||||
|             name="sandbox", |  | ||||||
|             with_=executor_with_config, |  | ||||||
|         ), |  | ||||||
|         parsers=( |  | ||||||
|             [result.Parser(name=parser, with_={}) for parser in task_stage.parsers] |  | ||||||
|             if task_stage.parsers is not None |  | ||||||
|             else [] |  | ||||||
|         ), |  | ||||||
|     ) |  | ||||||
|     return conf_stage |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def get_executorWithConfig( |  | ||||||
|     task_stage: task.Stage, cached: list[str] |  | ||||||
| ) -> Tuple[result.ExecutorWith, list[str]]: |  | ||||||
|     file_import = ( |  | ||||||
|         task_stage.files.import_ |  | ||||||
|         if hasattr(task_stage, "files") |  | ||||||
|         and hasattr(task_stage.files, "import_") |  | ||||||
|         and (task_stage.files is not None) |  | ||||||
|         and (task_stage.files.import_ is not None) |  | ||||||
|         else [] |  | ||||||
|     ) |  | ||||||
|     copy_in_files = [file for file in file_import if (file not in cached)] |  | ||||||
|     file_export = ( |  | ||||||
|         task_stage.files.export |  | ||||||
|         if hasattr(task_stage, "files") |  | ||||||
|         and hasattr(task_stage.files, "export") |  | ||||||
|         and (task_stage.files is not None) |  | ||||||
|         else [] |  | ||||||
|     ) |  | ||||||
|     executor_with_config = result.ExecutorWith( |  | ||||||
|         default=result.Cmd( |  | ||||||
|             args=(task_stage.command.split() if task_stage.command is not None else []), |  | ||||||
|             copy_in={ |  | ||||||
|                 file: result.CmdFile(src=f"/home/tt/.config/joj/{file}") |  | ||||||
|                 for file in copy_in_files |  | ||||||
|             }, |  | ||||||
|             copy_in_cached={file: file for file in copy_in_files}, |  | ||||||
|             copy_out_cached=file_export if file_export is not None else [], |  | ||||||
|             cpu_limit=( |  | ||||||
|                 task_stage.limit.cpu * 1_000_000_000 |  | ||||||
|                 if task_stage.limit is not None and task_stage.limit.cpu is not None |  | ||||||
|                 else 4 * 1_000_000_000 |  | ||||||
|             ), |  | ||||||
|             clock_limit=( |  | ||||||
|                 2 * task_stage.limit.cpu * 1_000_000_000 |  | ||||||
|                 if task_stage.limit is not None and task_stage.limit.cpu is not None |  | ||||||
|                 else 8 * 1_000_000_000 |  | ||||||
|             ), |  | ||||||
|             memory_limit=( |  | ||||||
|                 task_stage.limit.mem * 1_024 * 1_024 |  | ||||||
|                 if task_stage.limit is not None and task_stage.limit.mem is not None |  | ||||||
|                 else 4 * 1_024 * 1_024 |  | ||||||
|             ), |  | ||||||
|             stderr=result.CmdFile( |  | ||||||
|                 name="stderr", |  | ||||||
|                 max=( |  | ||||||
|                     task_stage.limit.stderr * 1_000_000_000 |  | ||||||
|                     if task_stage.limit is not None |  | ||||||
|                     and task_stage.limit.stderr is not None |  | ||||||
|                     else 4 * 1_024 * 1_024 |  | ||||||
|                 ), |  | ||||||
|             ), |  | ||||||
|             stdout=result.CmdFile( |  | ||||||
|                 name="stdout", |  | ||||||
|                 max=( |  | ||||||
|                     task_stage.limit.stdout * 1_000_000_000 |  | ||||||
|                     if task_stage.limit is not None |  | ||||||
|                     and task_stage.limit.stdout is not None |  | ||||||
|                     else 4 * 1_024 * 1_024 |  | ||||||
|                 ), |  | ||||||
|             ), |  | ||||||
|         ), |  | ||||||
|         cases=[],  # You can add cases if needed |  | ||||||
|     ) |  | ||||||
|     if file_export is not None: |  | ||||||
|         for file in file_export: |  | ||||||
|             if file not in cached: |  | ||||||
|                 cached.append(file) |  | ||||||
|     return (executor_with_config, cached) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def fix_keyword( |  | ||||||
|     task_stage: task.Stage, conf_stage: result.StageDetail |  | ||||||
| ) -> result.StageDetail: |  | ||||||
|     keyword_parser = ["clangtidy", "keyword", "cppcheck"]  # TODO: may add cpplint |     keyword_parser = ["clangtidy", "keyword", "cppcheck"]  # TODO: may add cpplint | ||||||
|     if task_stage.parsers is not None: |     for parser in task_stage.parsers: | ||||||
|         for parser in task_stage.parsers: |         if parser in keyword_parser: | ||||||
|             if parser in keyword_parser: |             keyword_parser_ = next(p for p in conf_stage.parsers if p.name == parser) | ||||||
|                 keyword_parser_ = next( |             keyword_weight = [] | ||||||
|                     p for p in conf_stage.parsers if p.name == parser |             if getattr(task_stage, parser, None) is not None: | ||||||
|                 ) |                 for _, keyword in enumerate(getattr(task_stage, parser).keyword): | ||||||
|                 keyword_weight = [] |                     keyword_weight.append({"keyword": [keyword], "score": 0}) | ||||||
|                 if getattr(task_stage, parser, None) is not None: |                 for idx, weight in enumerate(getattr(task_stage, parser).weight): | ||||||
|                     for _, keyword in enumerate(getattr(task_stage, parser).keyword): |                     keyword_weight[idx]["score"] = weight | ||||||
|                         keyword_weight.append({"keyword": [keyword], "score": 0}) |  | ||||||
|                     for idx, weight in enumerate(getattr(task_stage, parser).weight): |  | ||||||
|                         keyword_weight[idx]["score"] = weight |  | ||||||
| 
 |  | ||||||
|                 keyword_parser_.with_.update({"match": keyword_weight}) |  | ||||||
|             else: |  | ||||||
|                 continue |  | ||||||
|     return conf_stage |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def fix_result_detail( |  | ||||||
|     task_stage: task.Stage, conf_stage: result.StageDetail |  | ||||||
| ) -> result.StageDetail: |  | ||||||
|     if (task_stage.parsers is not None) and ("result-detail" in task_stage.parsers): |  | ||||||
|         result_detail_parser = next( |  | ||||||
|             p for p in conf_stage.parsers if p.name == "result-detail" |  | ||||||
|         ) |  | ||||||
|         if task_stage.result_detail is not None: |  | ||||||
|             show_files = [] |  | ||||||
|             if ( |  | ||||||
|                 task_stage.result_detail.stdout |  | ||||||
|                 and task_stage.result_detail.stdout is not None |  | ||||||
|             ): |  | ||||||
|                 show_files.append("stdout") |  | ||||||
|             if ( |  | ||||||
|                 task_stage.result_detail.stderr |  | ||||||
|                 and task_stage.result_detail.stderr is not None |  | ||||||
|             ): |  | ||||||
|                 show_files.append("stderr") |  | ||||||
|             result_detail_parser.with_.update( |  | ||||||
|                 { |  | ||||||
|                     "score": 0, |  | ||||||
|                     "comment": "", |  | ||||||
|                     "showFiles": show_files, |  | ||||||
|                     "showExitStatus": task_stage.result_detail.exitstatus, |  | ||||||
|                     "showRuntime": task_stage.result_detail.time, |  | ||||||
|                     "showMemory": task_stage.result_detail.mem, |  | ||||||
|                 } |  | ||||||
|             ) |  | ||||||
| 
 |  | ||||||
|     return conf_stage |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def fix_comment( |  | ||||||
|     task_stage: task.Stage, conf_stage: result.StageDetail |  | ||||||
| ) -> result.StageDetail: |  | ||||||
|     comment_parser = [ |  | ||||||
|         "dummy", |  | ||||||
|         "result-status", |  | ||||||
|         "cpplint", |  | ||||||
|     ]  # FIXME: determine where cpplint should be |  | ||||||
|     if task_stage.parsers is not None: |  | ||||||
|         for parser in task_stage.parsers: |  | ||||||
|             if parser in comment_parser: |  | ||||||
|                 comment_parser_ = next( |  | ||||||
|                     p for p in conf_stage.parsers if p.name == parser |  | ||||||
|                 ) |  | ||||||
|                 if getattr(task_stage, parser.replace("-", "_"), None) is not None: |  | ||||||
|                     comment_parser_.with_.update( |  | ||||||
|                         getattr(task_stage, parser.replace("-", "_")) |  | ||||||
|                     ) |  | ||||||
|             else: |  | ||||||
|                 continue |  | ||||||
|     return conf_stage |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def fix_diff( |  | ||||||
|     task_stage: task.Stage, conf_stage: result.StageDetail |  | ||||||
| ) -> result.StageDetail: |  | ||||||
|     if task_stage.parsers is not None and "diff" in task_stage.parsers: |  | ||||||
|         diff_parser = next((p for p in conf_stage.parsers if p.name == "diff"), None) |  | ||||||
|         skip = task_stage.skip or [] |  | ||||||
|         cases = task_stage.cases or {} |  | ||||||
|         finalized_cases = [case for case in cases if case not in skip] |  | ||||||
| 
 |  | ||||||
|         stage_cases = [] |  | ||||||
|         parser_cases = [] |  | ||||||
| 
 |  | ||||||
|         for case in finalized_cases: |  | ||||||
|             case_stage = task_stage.cases.get(case) if task_stage.cases else None |  | ||||||
|             if not case_stage: |  | ||||||
|                 continue |  | ||||||
| 
 |  | ||||||
|             # Ensure case_stage.limit is defined before accessing .cpu and .mem |  | ||||||
|             cpu_limit = ( |  | ||||||
|                 case_stage.limit.cpu * 1_000_000_000 |  | ||||||
|                 if case_stage.limit and case_stage.limit.cpu is not None |  | ||||||
|                 else 0 |  | ||||||
|             ) |  | ||||||
|             clock_limit = ( |  | ||||||
|                 2 * case_stage.limit.cpu * 1_000_000_000 |  | ||||||
|                 if case_stage.limit and case_stage.limit.cpu is not None |  | ||||||
|                 else 0 |  | ||||||
|             ) |  | ||||||
|             memory_limit = ( |  | ||||||
|                 case_stage.limit.mem * 1_024 * 1_024 |  | ||||||
|                 if case_stage.limit and case_stage.limit.mem is not None |  | ||||||
|                 else 0 |  | ||||||
|             ) |  | ||||||
| 
 |  | ||||||
|             stage_cases.append( |  | ||||||
|                 result.OptionalCmd( |  | ||||||
|                     stdin=result.CmdFile( |  | ||||||
|                         src=f"/home/tt/.config/joj/{conf_stage.name}/{case}.in" |  | ||||||
|                     ), |  | ||||||
|                     cpu_limit=cpu_limit, |  | ||||||
|                     clock_limit=clock_limit, |  | ||||||
|                     memory_limit=memory_limit, |  | ||||||
|                     proc_limit=50, |  | ||||||
|                 ) |  | ||||||
|             ) |  | ||||||
| 
 |  | ||||||
|             # Ensure case_stage.diff and case_stage.diff.output are defined |  | ||||||
|             diff_output = ( |  | ||||||
|                 case_stage.diff.output |  | ||||||
|                 if case_stage.diff and case_stage.diff.output |  | ||||||
|                 else None |  | ||||||
|             ) |  | ||||||
|             if diff_output: |  | ||||||
|                 parser_cases.append( |  | ||||||
|                     { |  | ||||||
|                         "outputs": [ |  | ||||||
|                             { |  | ||||||
|                                 "score": diff_output.score, |  | ||||||
|                                 "fileName": "stdout", |  | ||||||
|                                 "answerPath": f"/home/tt/.config/joj/{conf_stage.name}/{case}.out", |  | ||||||
|                                 "forceQuitOnDiff": diff_output.forcequit, |  | ||||||
|                                 "alwaysHide": diff_output.hide, |  | ||||||
|                                 "compareSpace": not diff_output.ignorespaces, |  | ||||||
|                             } |  | ||||||
|                         ] |  | ||||||
|                     } |  | ||||||
|                 ) |  | ||||||
| 
 |  | ||||||
|         if diff_parser and task_stage.diff is not None: |  | ||||||
|             diff_parser.with_.update({"name": "diff", "cases": parser_cases}) |  | ||||||
|             conf_stage.executor.with_.cases = stage_cases |  | ||||||
| 
 | 
 | ||||||
|  |             keyword_parser_.with_.update({"match": keyword_weight}) | ||||||
|  |         else: | ||||||
|  |             continue | ||||||
|     return conf_stage |     return conf_stage | ||||||
|  |  | ||||||
|  | @ -62,7 +62,6 @@ def convert(root: Path = Path(".")) -> result.Config: | ||||||
|         task_toml = task_file.read() |         task_toml = task_file.read() | ||||||
|     repo_obj = rtoml.loads(repo_toml) |     repo_obj = rtoml.loads(repo_toml) | ||||||
|     task_obj = rtoml.loads(task_toml) |     task_obj = rtoml.loads(task_toml) | ||||||
|     print(task_obj) |  | ||||||
|     result_model = convert_conf(Repo(**repo_obj), Task(**task_obj)) |     result_model = convert_conf(Repo(**repo_obj), Task(**task_obj)) | ||||||
|     result_dict = result_model.model_dump(by_alias=True) |     result_dict = result_model.model_dump(by_alias=True) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -18,8 +18,8 @@ class ParserDummy(BaseModel): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class ParserKeyword(BaseModel): | class ParserKeyword(BaseModel): | ||||||
|     keyword: Optional[list[str]] = None |     keyword: Optional[list[str]] = [] | ||||||
|     weight: Optional[list[int]] = None |     weight: Optional[list[int]] = [] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Files(BaseModel): | class Files(BaseModel): | ||||||
|  | @ -42,6 +42,7 @@ class Stage(BaseModel): | ||||||
|     parsers: list[str]  # list of parsers |     parsers: list[str]  # list of parsers | ||||||
|     limit: Optional[Limit] = None |     limit: Optional[Limit] = None | ||||||
|     dummy: Optional[ParserDummy] = ParserDummy() |     dummy: Optional[ParserDummy] = ParserDummy() | ||||||
|  |     result_status: Optional[ParserDummy] = Field(ParserDummy(), alias="result-status") | ||||||
|     keyword: Optional[ParserKeyword] = ParserKeyword() |     keyword: Optional[ParserKeyword] = ParserKeyword() | ||||||
|     clangtidy: Optional[ParserKeyword] = ParserKeyword() |     clangtidy: Optional[ParserKeyword] = ParserKeyword() | ||||||
|     cppcheck: Optional[ParserKeyword] = ParserKeyword() |     cppcheck: Optional[ParserKeyword] = ParserKeyword() | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	Block a user