11#!/usr/bin/env python3
2- import argparse
32import glob
43import os .path
54import platform
65import random
6+ from typing import Optional , List
77
8- from manager_pb2 import EvaluateTerryTaskRequest , TerrySolution
9- from task_pb2 import TerryTask , DEFAULT , X86_64 , I686
8+ from task_maker .args import Arch , CacheMode , UIS
9+ from task_maker .config import Config
10+ from task_maker .formats import get_options , TerryTask , list_files
11+ from task_maker .formats .ioi_format import parse_task_yaml
12+ from task_maker .source_file import SourceFile
13+ from task_maker .task_maker_frontend import Frontend
14+ from task_maker .uis .terry import TerryUIInterface
15+ from task_maker .uis .terry_curses_ui import TerryCursesUI
16+ from task_maker .uis .terry_finish_ui import TerryFinishUI
1017
11- from task_maker .absolutize import absolutize_source_file , absolutize_path
12- from task_maker .formats .ioi_format import parse_task_yaml , get_options , \
13- list_files
14- from task_maker .source_file import from_file
1518
16-
17- def get_extension (target_arch = DEFAULT ):
18- if target_arch == DEFAULT :
19+ def get_extension (target_arch : Arch ):
20+ if target_arch == Arch .DEFAULT :
1921 return "." + platform .system ().lower () + "." + platform .machine ()
20- elif target_arch == X86_64 :
22+ elif target_arch == Arch . X86_64 :
2123 return "." + platform .system ().lower () + ".x86_64"
22- elif target_arch == I686 :
24+ elif target_arch == Arch . I686 :
2325 return "." + platform .system ().lower () + ".i686"
2426 else :
2527 raise ValueError ("Unsupported architecture" )
2628
2729
28- def create_task_from_yaml (data ):
30+ def create_task_from_yaml (data ) -> TerryTask :
2931 name = get_options (data , ["name" , "nome_breve" ])
3032 title = get_options (data , ["description" , "nome" ])
3133 max_score = get_options (data , ["max_score" ])
@@ -34,14 +36,23 @@ def create_task_from_yaml(data):
3436 if title is None :
3537 raise ValueError ("The title is not set in the yaml" )
3638
37- task = TerryTask ()
38- task .name = name
39- task .title = title
40- task .max_score = max_score
41- return task
39+ return TerryTask (name , title , max_score )
40+
41+
42+ def get_solutions (solutions ) -> List [str ]:
43+ if solutions :
44+ solutions = list_files ([
45+ sol + "*"
46+ if sol .startswith ("solutions/" ) else "solutions/" + sol + "*"
47+ for sol in solutions
48+ ])
49+ else :
50+ solutions = list_files (["solutions/*" ], exclude = ["sol/__init__.py" ])
51+ return solutions
4252
4353
44- def get_manager (manager , target_arch , optional = False ):
54+ def get_manager (manager : str , target_arch : Arch ,
55+ optional : bool = False ) -> Optional [SourceFile ]:
4556 managers = list_files (
4657 ["managers/%s.*" % manager ], exclude = ["managers/%s.*.*" % manager ])
4758 if len (managers ) == 0 :
@@ -50,70 +61,122 @@ def get_manager(manager, target_arch, optional=False):
5061 return None
5162 if len (managers ) != 1 :
5263 raise ValueError ("Ambiguous manager: " + ", " .join (managers ))
53- return from_file (managers [0 ],
54- "managers/%s%s" % (manager , get_extension (target_arch )),
55- target_arch )
64+ return SourceFile .from_file (
65+ managers [0 ], manager , True ,
66+ "managers/%s%s" % (manager , get_extension (target_arch )), target_arch ,
67+ {})
5668
5769
58- def get_request (args : argparse . Namespace ):
70+ def get_request (config : Config ) -> ( TerryTask , List [ SourceFile ] ):
5971 data = parse_task_yaml ()
6072 if not data :
6173 raise RuntimeError ("The task.yaml is not valid" )
6274
6375 task = create_task_from_yaml (data )
6476
65- task .generator .CopyFrom (get_manager ("generator" , args .arch .value ))
66- absolutize_source_file (task .generator )
77+ task .generator = get_manager ("generator" , config .arch )
78+ task .validator = get_manager ("validator" , config .arch , optional = True )
79+ task .official_solution = get_manager (
80+ "solution" , config .arch , optional = True )
81+ task .checker = get_manager ("checker" , config .arch )
82+
83+ solutions = get_solutions (config .solutions )
84+ sols = [] # type: List[SourceFile]
85+ for solution in solutions :
86+ path , ext = os .path .splitext (os .path .basename (solution ))
87+ source = SourceFile .from_file (solution , task .name , config .copy_exe ,
88+ "bin/" + path + "_" + ext [1 :],
89+ Arch .DEFAULT , {})
90+ sols .append (source )
91+
92+ return task , sols
93+
94+
95+ def evaluate_task (frontend : Frontend , task : TerryTask ,
96+ solutions : List [SourceFile ], config : Config ):
97+ ui_interface = TerryUIInterface (task , config .ui == UIS .PRINT )
98+ if config .ui == UIS .CURSES :
99+ curses_ui = TerryCursesUI (ui_interface )
100+ curses_ui .start ()
101+
102+ task .generator .prepare (frontend , config )
103+ ui_interface .add_non_solution (task .generator )
104+ if task .validator :
105+ task .validator .prepare (frontend , config )
106+ ui_interface .add_non_solution (task .validator )
107+ if task .official_solution :
108+ task .official_solution .prepare (frontend , config )
109+ ui_interface .add_non_solution (task .official_solution )
110+ task .checker .prepare (frontend , config )
111+ ui_interface .add_non_solution (task .checker )
112+
113+ for solution in solutions :
114+ solution .prepare (frontend , config )
115+ ui_interface .add_solution (solution )
116+ evaluate_solution (frontend , task , solution , config , ui_interface )
67117
68- validator = get_manager ("validator" , args .arch .value , optional = True )
69- if validator :
70- task .validator .CopyFrom (validator )
71- absolutize_source_file (task .validator )
118+ frontend .evaluate ()
72119
73- task .checker .CopyFrom (get_manager ("checker" , args .arch .value ))
74- absolutize_source_file (task .checker )
120+ if config .ui == UIS .CURSES :
121+ curses_ui .stop ()
122+ if config .ui != UIS .SILENT :
123+ finish_ui = TerryFinishUI (config , task , ui_interface )
124+ finish_ui .print ()
125+ return ui_interface
75126
76- solution = get_manager ("solution" , args .arch .value , optional = True )
77- if solution :
78- task .solution .CopyFrom (solution )
79- absolutize_source_file (task .solution )
80127
81- if args .solutions :
82- solutions = list_files ([
83- sol + "*"
84- if sol .startswith ("solutions/" ) else "solutions/" + sol + "*"
85- for sol in args .solutions
86- ])
128+ def evaluate_solution (frontend : Frontend , task : TerryTask ,
129+ solution : SourceFile , config : Config ,
130+ interface : TerryUIInterface ):
131+ if config .seed :
132+ seed = config .seed
87133 else :
88- solutions = list_files (
89- ["solutions/*" ], exclude = ["solutions/__init__.py" ])
90-
91- request = EvaluateTerryTaskRequest ()
92- request .task .CopyFrom (task )
93- copy_compiled = args .copy_exe
94- for solution in solutions :
95- path , ext = os .path .splitext (os .path .basename (solution ))
96- bin_file = copy_compiled and "bin/" + path + "_" + ext [1 :]
97- source_file = from_file (solution , bin_file )
98- absolutize_source_file (source_file )
99- terry_solution = TerrySolution ()
100- terry_solution .solution .CopyFrom (source_file )
101- if args .seed :
102- terry_solution .seed = args .seed
103- else :
104- terry_solution .seed = random .randint (0 , 2 ** 32 - 1 )
105- request .solutions .extend ([terry_solution ])
106- request .store_dir = absolutize_path (args .store_dir )
107- request .temp_dir = absolutize_path (args .temp_dir )
108- request .cache_mode = args .cache .value
109- if args .num_cores :
110- request .num_cores = args .num_cores
111- request .dry_run = args .dry_run
112- if args .evaluate_on :
113- request .evaluate_on = args .evaluate_on
114- request .keep_sandbox = args .keep_sandbox
115- request .exclusive = args .exclusive
116- return request
134+ seed = random .randint (0 , 2 ** 31 - 1 )
135+ name = solution .name
136+
137+ generation = task .generator .execute (
138+ frontend , "Generation of input for solution {} with seed {}" .format (
139+ name , seed ), [str (seed ), "0" ])
140+ if config .cache == CacheMode .NOTHING :
141+ generation .disableCache ()
142+ input = generation .stdout (False )
143+ if task .official_solution :
144+ generation .addInput (task .official_solution .exe_name ,
145+ task .official_solution .executable )
146+ interface .add_generation (name , seed , generation )
147+
148+ if task .validator :
149+ validation = task .validator .execute (
150+ frontend , "Validation of input for solution {}" .format (name ),
151+ ["0" ])
152+ if config .cache == CacheMode .NOTHING :
153+ validation .disableCache ()
154+ validation .setStdin (input )
155+ if task .official_solution :
156+ validation .addInput (task .official_solution .exe_name ,
157+ task .official_solution .executable )
158+ interface .add_validation (name , validation )
159+
160+ solving = solution .execute (frontend , "Running solution {}" .format (name ),
161+ [])
162+ if config .cache != CacheMode .ALL :
163+ solving .disableCache ()
164+ solving .setStdin (input )
165+ if task .validator :
166+ solving .addInput ("wait_for_validation" , validation .stdout (False ))
167+ output = solving .stdout (False )
168+ interface .add_solving (name , solving )
169+
170+ checker = task .checker .execute (
171+ frontend , "Checking solution {}" .format (name ), ["input" , "output" ])
172+ if config .cache == CacheMode .NOTHING :
173+ checker .disableCache ()
174+ checker .addInput ("input" , input )
175+ checker .addInput ("output" , output )
176+ if task .official_solution :
177+ checker .addInput (task .official_solution .exe_name ,
178+ task .official_solution .executable )
179+ interface .add_checking (name , checker )
117180
118181
119182def clean ():
0 commit comments