def build_binary(src_fn): u"Build the binary for `src_fn`." ui.start_task(src_fn) exe_fn = change_extension(src_fn, 'exe') # get compilers from environment gcc = os.getenv('CC') if not gcc: gcc = 'gcc' gpp = os.getenv('CXX') if not gpp: gpp = 'g++' if src_fn.endswith('.c'): cmd_line = '%s -O2 -lm -std=c99 -o %s %s' % (gcc, exe_fn, src_fn) elif src_fn.endswith('.cpp'): cmd_line = '%s -std=c++11 -O2 -o %s %s' % (gpp, exe_fn, src_fn) elif src_fn.endswith('.pas'): cmd_line = 'fpc -O2 -Tlinux -o%s %s' % (exe_fn, src_fn) elif src_fn.endswith('.java'): exe_fn = change_extension(src_fn, 'exe') cmd_line = ('javac %s && ln -sf `pwd`/.box/run_java.sh %s && ' 'chmod a+x %s' % (src_fn, exe_fn, exe_fn)) elif src_fn.endswith('.py'): exe_fn = change_extension(src_fn, 'exe') cmd_line = 'ln -sf `pwd`/%s %s && chmod a+x %s' % (src_fn, exe_fn, exe_fn) else: ui.show_message('Error', 'Unknown extension for source file.', ERROR) ui.end_task('failed') if subprocess.call(cmd_line, shell=True) == 0: ui.end_task('OK') else: ui.end_task('failed')
def build_pdf(output_fn, *tex_fns): u"Compile the `tex_fns` files to a PDF named `output_fn`." if os.path.exists('.build'): shutil.rmtree('.build') # remove old content os.mkdir('.build') tex_input = NamedTemporaryFile(suffix='.tex', delete=False) with open('.box/defs.tex', 'r') as tex_defs: tex_input.write(tex_defs.read()) print >> tex_input, '\\newcommand{\\CWD}{.}' print >> tex_input, '\\begin{document}' for tex_fn in tex_fns: print >> tex_input, '\\renewcommand{\\CWD}{%s}' % \ os.path.dirname(tex_fn) with open(tex_fn, 'r') as tex_file: tex_input.write(tex_file.read()) print >> tex_input, '\\end{document}' tex_input.close() log_fn = change_extension(output_fn, 'log') ui.start_task(output_fn) if subprocess.call([ 'pdflatex', '-halt-on-error', '-file-line-error', '-output-directory', '.build', '-jobname=output', '-interaction=nonstopmode', tex_input.name ], stdout=NamedTemporaryFile(), stderr=NamedTemporaryFile()) == 0: shutil.move('.build/output.pdf', output_fn) ui.end_task('OK') else: ui.end_task('failed') shutil.move('.build/output.log', log_fn)
def box_build_output(name): u"Build output file for problem `name`." global short_mode if short_mode: OK_msg, failed_msg, short = '.', 'X', 'short' else: OK_msg, failed_msg, short = 'OK', 'failed', None if reference_solution(name) is None: ui.task_header(name, 'Generating problem output...') ui.show_message('Error', 'No good solutions available.', ERROR) hints.give_hint('output-good-solutions') return False else: ui.task_header( name, 'Generating problem output with %s...' % os.path.basename(reference_solution(name))) for input_fn in input_files(name): output_fn = change_extension(input_fn, 'sol') if not short_mode: ui.start_task(output_fn) if build_one_output(name, input_fn): ui.end_task(OK_msg, OK, short) else: ui.end_task(failed_msg, ERROR, short) if short: print return True
def run_checker(checker_fn): u"Run a single checker program against the input file." ui.task_header( name, 'Validating input with %s...' % os.path.basename(checker_fn)) if not os.access(checker_fn, os.X_OK): ui.show_message('Warning', '%s is not an executable.' % checker_fn, WARNING) return for input_fn in sample_input_files(name) + input_files(name): if not short_mode: ui.start_task(input_fn) with open(input_fn, 'r') as input_file: with open('/dev/null', 'w') as dev_null: if subprocess.call(checker_fn, stdin=input_file, stdout=dev_null, stderr=dev_null) != 0: ui.end_task(failed_msg, ERROR, short) else: ui.end_task(OK_msg, OK, short)
def box_build_input(name): u"Build the input file for problem `name`." ui.task_header(name, 'Building generators...') build_binaries('%s/attic/' % name) ui.task_header(name, 'Generating input files...') clean.clean_build(name) if not os.path.exists('%s/build/' % name): os.mkdir('%s/build/' % name) if not os.path.exists('%s/build/tests/' % name): os.mkdir('%s/build/tests/' % name) ui.start_task('%s/attic/build-tests' % name) OK_msg, failed_msg, short = 'OK', 'failed', None my_env = os.environ.copy() my_env['ROOT'] = '%s' % name with NamedTemporaryFile('w') as error_file: error_file.write('test') try: res_proc = subprocess.check_call(['%s/attic/build-tests' % name], env=my_env, stderr=error_file) if res_proc == 0: ui.end_task(OK_msg, OK, short) else: ui.end_task(failed_msg, ERROR, short) print >> sys.stderr, '\nError messages:\n---------------' with open(error_file.name, 'r') as efile: print >> sys.stderr, efile.read() print >> sys.stderr, '---------------' except: ui.end_task(failed_msg, ERROR, short) print >> sys.stderr, '\nError messages:\n---------------' with open(error_file.name, 'r') as efile: print >> sys.stderr, efile.read() print >> sys.stderr, '---------------' size = 0 for i in input_files(name): size += os.path.getsize(i) print ' %d tests built (%s)' % (len(input_files(name)), sizeof_fmt(size))
def run_check(name, sol_group, ctime_limit=100, jtime_limit=100, ptime_limit=100): for sol_fn, expected in solutions(name, sol_group): cur_cref_solutions_time,cur_jref_solutions_time,cur_pref_solutions_time=[],[],[] cur_cref_solutions_totaltime,cur_jref_solutions_totaltime,cur_pref_solutions_totaltime=[],[],[] solution_language = check_solution_language(sol_fn) ui.task_header( name, 'Testing %s [%s,%s] on REAL input...' % (os.path.basename(sol_fn), sol_group, solution_language)) basename, extension = os.path.splitext(sol_fn) mem_limit = 1024 file_limit = 1024 if solution_language == 'java': time_limit = jtime_limit mem_limit = 2048 elif solution_language == 'python': time_limit = ptime_limit else: time_limit = ctime_limit for input_fn in input_files(name): if not short_mode: ui.start_task(input_fn) result = run_solution(sol_fn, input_fn, reference_fn=change_extension( input_fn, 'sol'), time_limit=time_limit, mem_limit=mem_limit, file_limit=file_limit) if result.status == 'RE': ui.end_task(exec_msg, ERROR, short) #ui.end_task(result.detail, ERROR, short) elif result.status == 'TLE': color = [WARNING, OK][expected == result.status] ui.end_task(timeout_msg, color, short) elif result.status == 'WA': color = [ERROR, OK][expected == 'WA'] if do_time: ui.end_task('%4.2fs ' % result.running_time, color, short) else: ui.end_task(wrong_msg, color, short) elif result.status == 'AC': color = [ERROR, OK][expected == 'AC'] if do_time: ui.end_task('%4.2fs ' % result.running_time, color, short) else: ui.end_task(OK_msg, color, short) else: assert False if expected == 'AC': if solution_language == 'java': cur_jref_solutions_time.append(result.running_time) elif solution_language == 'python': cur_pref_solutions_time.append(result.running_time) else: # lang is c/c++ cur_cref_solutions_time.append(result.running_time) if len(cur_cref_solutions_time) != 0: cref_solutions_maxtime.append(max(cur_cref_solutions_time)) cref_solutions_mintime.append(min(cur_cref_solutions_time)) cref_solutions_totaltime.append(sum(cur_cref_solutions_time)) print ' Total time: %.2fs (worst case: %.2fs)' % ( sum(cur_cref_solutions_time), max(cur_cref_solutions_time)) if len(cur_jref_solutions_time) != 0: jref_solutions_maxtime.append(max(cur_jref_solutions_time)) jref_solutions_mintime.append(min(cur_jref_solutions_time)) jref_solutions_totaltime.append(sum(cur_jref_solutions_time)) print ' Total time: %.2fs (worst case: %.2fs)' % ( sum(cur_jref_solutions_time), max(cur_jref_solutions_time)) if len(cur_pref_solutions_time) != 0: pref_solutions_maxtime.append(max(cur_pref_solutions_time)) pref_solutions_mintime.append(min(cur_pref_solutions_time)) pref_solutions_totaltime.append(sum(cur_pref_solutions_time)) print ' Total time: %.2fs (worst case: %.2fs)' % ( sum(cur_pref_solutions_time), max(cur_pref_solutions_time)) return
def box_check_solutions(name, sol_groups, do_time=False, do_sample=False): u"Check all solutions for problem `name`." global short_mode def check_solution_language(fsolname): with open(fsolname, 'r') as fsol: first_line = fsol.readline() if first_line.find('#!') == 0: if first_line.find('python') > 0: t = 'python' else: t = 'java' else: t = 'c/c++' return t def run_check(name, sol_group, ctime_limit=100, jtime_limit=100, ptime_limit=100): for sol_fn, expected in solutions(name, sol_group): cur_cref_solutions_time,cur_jref_solutions_time,cur_pref_solutions_time=[],[],[] cur_cref_solutions_totaltime,cur_jref_solutions_totaltime,cur_pref_solutions_totaltime=[],[],[] solution_language = check_solution_language(sol_fn) ui.task_header( name, 'Testing %s [%s,%s] on REAL input...' % (os.path.basename(sol_fn), sol_group, solution_language)) basename, extension = os.path.splitext(sol_fn) mem_limit = 1024 file_limit = 1024 if solution_language == 'java': time_limit = jtime_limit mem_limit = 2048 elif solution_language == 'python': time_limit = ptime_limit else: time_limit = ctime_limit for input_fn in input_files(name): if not short_mode: ui.start_task(input_fn) result = run_solution(sol_fn, input_fn, reference_fn=change_extension( input_fn, 'sol'), time_limit=time_limit, mem_limit=mem_limit, file_limit=file_limit) if result.status == 'RE': ui.end_task(exec_msg, ERROR, short) #ui.end_task(result.detail, ERROR, short) elif result.status == 'TLE': color = [WARNING, OK][expected == result.status] ui.end_task(timeout_msg, color, short) elif result.status == 'WA': color = [ERROR, OK][expected == 'WA'] if do_time: ui.end_task('%4.2fs ' % result.running_time, color, short) else: ui.end_task(wrong_msg, color, short) elif result.status == 'AC': color = [ERROR, OK][expected == 'AC'] if do_time: ui.end_task('%4.2fs ' % result.running_time, color, short) else: ui.end_task(OK_msg, color, short) else: assert False if expected == 'AC': if solution_language == 'java': cur_jref_solutions_time.append(result.running_time) elif solution_language == 'python': cur_pref_solutions_time.append(result.running_time) else: # lang is c/c++ cur_cref_solutions_time.append(result.running_time) if len(cur_cref_solutions_time) != 0: cref_solutions_maxtime.append(max(cur_cref_solutions_time)) cref_solutions_mintime.append(min(cur_cref_solutions_time)) cref_solutions_totaltime.append(sum(cur_cref_solutions_time)) print ' Total time: %.2fs (worst case: %.2fs)' % ( sum(cur_cref_solutions_time), max(cur_cref_solutions_time)) if len(cur_jref_solutions_time) != 0: jref_solutions_maxtime.append(max(cur_jref_solutions_time)) jref_solutions_mintime.append(min(cur_jref_solutions_time)) jref_solutions_totaltime.append(sum(cur_jref_solutions_time)) print ' Total time: %.2fs (worst case: %.2fs)' % ( sum(cur_jref_solutions_time), max(cur_jref_solutions_time)) if len(cur_pref_solutions_time) != 0: pref_solutions_maxtime.append(max(cur_pref_solutions_time)) pref_solutions_mintime.append(min(cur_pref_solutions_time)) pref_solutions_totaltime.append(sum(cur_pref_solutions_time)) print ' Total time: %.2fs (worst case: %.2fs)' % ( sum(cur_pref_solutions_time), max(cur_pref_solutions_time)) return if short_mode: OK_msg, timeout_msg, wrong_msg, exec_msg, short = '.', 'T', 'W', 'X', 'short' else: OK_msg, timeout_msg, wrong_msg, exec_msg, short = 'OK', 'timeout', 'wrong', 'failed', None # problem specs, to be read or calculated # using this only for the sample jtime_limit = 60 ctime_limit = 60 ptime_limit = 60 if do_sample: for sol_fn, expected in solutions(name, "good"): solution_language = check_solution_language(sol_fn) ui.task_header( name, 'Testing %s [%s,%s] on sample input...' % (os.path.basename(sol_fn), "good", solution_language)) for input_fn in sample_input_files(name): if not short_mode: ui.start_task(input_fn) basename, extension = os.path.splitext(sol_fn) mem_limit = 1024 file_limit = 1024 if solution_language == 'java': time_limit = jtime_limit mem_limit = 2048 elif solution_language == 'python': time_limit = ptime_limit else: time_limit = ctime_limit result = run_solution(sol_fn, input_fn, reference_fn=change_extension( input_fn, 'sol'), time_limit=time_limit, mem_limit=mem_limit, file_limit=file_limit) if result.status == 'RE': #ui.end_task(exec_msg, ERROR, short) ui.end_task(result.detail, ERROR, short) elif result.status == 'TLE': color = [WARNING, OK][expected == result.status] ui.end_task(timeout_msg, color, short) elif result.status == 'WA': color = [ERROR, OK][expected == 'WA'] ui.end_task(wrong_msg, color, short) hints.give_hint('solution-wrong-sample') elif result.status == 'AC': color = [ERROR, OK][expected == 'AC'] ui.end_task(OK_msg, color, short) else: assert False cref_solutions_maxtime,cref_solutions_mintime,cref_solutions_totaltime=[],[],[] jref_solutions_maxtime,jref_solutions_mintime,jref_solutions_totaltime=[],[],[] pref_solutions_maxtime,pref_solutions_mintime,pref_solutions_totaltime=[],[],[] if "good" in sol_groups: # will calculate time limits run_check(name, 'good') if short_mode: print if len(cref_solutions_maxtime) == 0: # no C solutions print >> sys.stderr, "Must have at least one C solution to calculate time limits!" ctime_limit = timelimit(cref_solutions_maxtime, C_LANG) if len(jref_solutions_maxtime) == 0: # no Java solutions jtime_limit = timelimit(cref_solutions_maxtime, JAVA_LANG) else: jtime_limit = timelimit(jref_solutions_maxtime, JAVA_LANG) if len(pref_solutions_maxtime) == 0: # no Python solutions ptime_limit = timelimit(cref_solutions_maxtime, PYTHON_LANG) else: ptime_limit = timelimit(pref_solutions_maxtime, PYTHON_LANG) # write time limits in file attic/problem.desc try: os.mkdir('%s/attic' % name) except: pass with open('%s/attic/problem.desc' % name, 'w') as desc_fn: desc_fn.write( 'time_limit_c=%.2f\ntime_limit_java=%.2f\ntime_limit_python=%.2f\n' % (ctime_limit, jtime_limit, ptime_limit)) desc_fn.write( "C=(%s,%s,%s)\n" % (str(cref_solutions_mintime), str(cref_solutions_maxtime), str(cref_solutions_totaltime))) desc_fn.write( "Java=(%s,%s,%s)\n" % (str(jref_solutions_mintime), str(jref_solutions_maxtime), str(jref_solutions_totaltime))) desc_fn.write( "Python=(%s,%s,%s)\n" % (str(pref_solutions_mintime), str(pref_solutions_maxtime), str(pref_solutions_totaltime))) box_report(name) # read time_limits from file attic/problem.desc if "good" not in sol_groups if not os.path.exists('%s/attic/problem.desc' % name): ui.show_message( 'Error', 'Please run check-solutions-good before to calculate time limits.', ERROR) return context = {} execfile(os.path.join(name, 'attic', 'problem.desc'), context) ct, jt, pt = context['time_limit_c'], context['time_limit_java'], context[ 'time_limit_python'] if ct == 60 and jt == 60 and pt == 60: ui.show_message( 'Error', 'Please run check-solutions-good before to calculate time limits.', ERROR) return if "pass" in sol_groups: run_check(name, 'pass', ct, jt, pt) if short_mode: print if "wrong" in sol_groups: run_check(name, 'wrong', ct, jt, pt) if short_mode: print if "slow" in sol_groups: run_check(name, 'slow', ct, jt, pt) if short_mode: print