1919class Utilities :
2020
2121 cache_dir = os .path .join (os .path .expanduser ("~" ), ".cache" , "ACedIt" )
22+ colors = {
23+ 'GREEN' : '\033 [92m' ,
24+ 'YELLOW' : '\033 [93m' ,
25+ 'RED' : '\033 [91m' ,
26+ 'ENDC' : '\033 [0m' ,
27+ 'BOLD' : '\033 [1m' ,
28+ }
2229
2330 @staticmethod
2431 def parse_flags ():
@@ -45,6 +52,10 @@ def parse_flags():
4552 action = "store_true" ,
4653 help = "Force download the test cases, even if they are cached" )
4754
55+ parser .add_argument ("--run" ,
56+ dest = "source_file" ,
57+ help = "Name of source file to be run" )
58+
4859 parser .set_defaults (force = False )
4960
5061 args = parser .parse_args ()
@@ -55,7 +66,7 @@ def parse_flags():
5566 import json
5667 default_site = None
5768 try :
58- with open ("constants.json" , "r" ) as f :
69+ with open (os . path . join ( Utilities . cache_dir , "constants.json" ) , "r" ) as f :
5970 data = f .read ()
6071 data = json .loads (data )
6172 default_site = data .get ("default_site" , None )
@@ -70,6 +81,7 @@ def parse_flags():
7081 flags ["problem" ] = args .problem
7182 flags ["force" ] = args .force
7283 flags ["site" ] = flags ["site" ].lower ()
84+ flags ["source" ] = args .source_file
7385
7486 return flags
7587
@@ -111,6 +123,9 @@ def store_files(site, contest, problem, inputs, outputs):
111123
112124 @staticmethod
113125 def download_problem_testcases (args ):
126+ """
127+ Download test cases for a given problem
128+ """
114129 if args ["site" ] == "codeforces" :
115130 platform = Codeforces (args )
116131 elif args ["site" ] == "codechef" :
@@ -131,6 +146,9 @@ def download_problem_testcases(args):
131146
132147 @staticmethod
133148 def download_contest_testcases (args ):
149+ """
150+ Download test cases for all problems in a given contest
151+ """
134152 if args ["site" ] == "codeforces" :
135153 platform = Codeforces (args )
136154 elif args ["site" ] == "codechef" :
@@ -143,6 +161,168 @@ def download_contest_testcases(args):
143161
144162 platform .scrape_contest ()
145163
164+ @staticmethod
165+ def input_file_to_string (path , num_cases ):
166+ """
167+ Method to return sample inputs as a list
168+ """
169+ inputs = []
170+
171+ for i in xrange (num_cases ):
172+ with open (os .path .join (path , 'Input' + str (i )), 'r' ) as fh :
173+ inputs += [fh .read ()]
174+
175+ return inputs
176+
177+ @staticmethod
178+ def cleanup (num_cases ):
179+ """
180+ Method to clean up temporarily created files
181+ """
182+ for i in xrange (num_cases ):
183+ if os .path .isfile ('temp_output' + str (i )):
184+ os .remove ('temp_output' + str (i ))
185+
186+ @staticmethod
187+ def run_solution (problem ):
188+ """
189+ Method to run and test the user's solution against sample cases
190+ """
191+ extension = problem .split ('.' )[- 1 ]
192+ problem = problem .split ('.' )[0 ]
193+ problem_path = os .path .join (os .getcwd (), problem )
194+
195+ if not os .path .isfile (problem_path + '.' + extension ):
196+ print "ERROR : No such file"
197+ sys .exit (0 )
198+
199+ testcases_path = os .path .join (
200+ Utilities .cache_dir , * problem_path .split ('/' )[- 3 :])
201+
202+ if os .path .isdir (testcases_path ):
203+ num_cases = len (os .listdir (testcases_path )) / 2
204+ results , expected_outputs , user_outputs = [], [], []
205+
206+ if extension == 'py' :
207+
208+ for i in xrange (num_cases ):
209+ status = os .system ('cat ' + os .path .join (testcases_path , 'Input' + str (
210+ i )) + ' | timeout 3s python ' + problem + '.py > temp_output' + str (i ))
211+ if status == 124 :
212+ # Time Limit Exceeded
213+ results += [Utilities .colors ['BOLD' ] +
214+ Utilities .colors ['YELLOW' ] + 'TLE' + Utilities .colors ['ENDC' ]]
215+
216+ elif status == 0 :
217+
218+ with open ('temp_output' + str (i ), 'r' ) as temp_handler , open (os .path .join (testcases_path , 'Output' + str (i )), 'r' ) as out_handler :
219+ expected_output = out_handler .read ().strip ()
220+ user_output = temp_handler .read ().strip ()
221+
222+ expected_outputs += [expected_output ]
223+ user_outputs += [user_output ]
224+
225+ if expected_output == user_output :
226+ # All Correct
227+ results += [Utilities .colors ['BOLD' ] + Utilities .colors [
228+ 'GREEN' ] + 'AC' + Utilities .colors ['ENDC' ]]
229+ else :
230+ # Wrong Answer
231+ results += [Utilities .colors ['BOLD' ] +
232+ Utilities .colors ['RED' ] + 'WA' + Utilities .colors ['ENDC' ]]
233+
234+ else :
235+ # Runtime Error
236+ results += [Utilities .colors ['BOLD' ] +
237+ Utilities .colors ['RED' ] + 'RTE' + Utilities .colors ['ENDC' ]]
238+
239+ elif extension == 'cpp' or extension == 'c' :
240+
241+ compiler = {'c' : 'gcc' , 'cpp' : 'g++' }[extension ]
242+ compile_status = os .system (
243+ compiler + ' ' + problem_path + '.cpp' )
244+
245+ if compile_status == 0 :
246+ for i in xrange (num_cases ):
247+ status = os .system ('timeout 2s ./a.out < ' + os .path .join (
248+ testcases_path , 'Input' + str (i )) + ' > temp_output' + str (i ))
249+ if status == 124 :
250+ # Time Limit Exceeded
251+ results += [Utilities .colors ['BOLD' ] + Utilities .colors [
252+ 'YELLOW' ] + 'TLE' + Utilities .colors ['ENDC' ]]
253+
254+ elif status == 0 :
255+
256+ with open ('temp_output' + str (i ), 'r' ) as temp_handler , open (os .path .join (testcases_path , 'Output' + str (i )), 'r' ) as out_handler :
257+ expected_output = out_handler .read ().strip ()
258+ user_output = temp_handler .read ().strip ()
259+
260+ expected_outputs += [expected_output ]
261+ user_outputs += [user_output ]
262+
263+ if expected_output == user_output :
264+ # All Correct
265+ results += [Utilities .colors ['BOLD' ] + Utilities .colors [
266+ 'GREEN' ] + 'AC' + Utilities .colors ['ENDC' ]]
267+ else :
268+ # Wrong Answer
269+ results += [Utilities .colors ['BOLD' ] + Utilities .colors [
270+ 'RED' ] + 'WA' + Utilities .colors ['ENDC' ]]
271+
272+ else :
273+ # Runtime Error
274+ results += [Utilities .colors ['BOLD' ] +
275+ Utilities .colors ['RED' ] + 'RTE' + Utilities .colors ['ENDC' ]]
276+ else :
277+ # Compilation error occurred
278+ message = Utilities .colors ['BOLD' ] + Utilities .colors [
279+ 'RED' ] + "Compilation error. Not run against test cases" + Utilities .colors ['ENDC' ] + "."
280+ print message
281+ sys .exit (0 )
282+
283+ else :
284+ print "Unsupported language."
285+ sys .exit (0 )
286+
287+ from terminaltables import AsciiTable
288+ table_data = [['Serial No' , 'Input' ,
289+ 'Expected Output' , 'Your Output' , 'Result' ]]
290+
291+ inputs = Utilities .input_file_to_string (testcases_path , num_cases )
292+
293+ for i in xrange (num_cases ):
294+
295+ row = [
296+ i + 1 ,
297+ inputs [i ],
298+ expected_outputs [i ],
299+ user_outputs [i ] if any (sub in results [i ]
300+ for sub in ['AC' , 'WA' ]) else 'N/A' ,
301+ results [i ]
302+ ]
303+
304+ table_data .append (row )
305+
306+ table = AsciiTable (table_data )
307+
308+ print table .table
309+
310+ else :
311+ print "Test cases not found locally..."
312+ args = {
313+ 'site' : testcases_path .split ('/' )[- 3 ],
314+ 'contest' : testcases_path .split ('/' )[- 2 ],
315+ 'problem' : testcases_path .split ('/' )[- 1 ],
316+ 'force' : True
317+ }
318+ Utilities .download_problem_testcases (args )
319+
320+ print "Done. Running your solution against sample cases..."
321+ Utilities .run_solution (problem )
322+
323+ # Clean up temporary files
324+ Utilities .cleanup (num_cases )
325+
146326 @staticmethod
147327 def get_html (url ):
148328 """
0 commit comments