|
| 1 | +"""Create a contest configuration file automatically. |
| 2 | +
|
| 3 | +Usage: |
| 4 | + limejudge autocreate [options] |
| 5 | + limejudge autocreate --help |
| 6 | +
|
| 7 | +Options: |
| 8 | + -c, --contest=<file> Write contest configuration to this file. |
| 9 | + [default: contest.yaml] |
| 10 | + -f, --force Force writing contest configuration even if |
| 11 | + the file already exists. |
| 12 | + --cflags=<flags> Use extra C compiler flags for this contest. |
| 13 | + --cxxflags=<flags> Use extra C++ compiler flags for this contest. |
| 14 | + -h, --help Print this help message and exit. |
| 15 | +""" |
| 16 | + |
| 17 | +import os |
| 18 | +import sys |
| 19 | +from glob import glob |
| 20 | + |
| 21 | +import yaml |
| 22 | +from docopt import docopt |
| 23 | + |
| 24 | + |
| 25 | +def ask_resource_limits(probname): |
| 26 | + time_limit = input( |
| 27 | + 'What is the time limit (in s) for "' + probname + '"? ') |
| 28 | + time_limit = float(time_limit) |
| 29 | + if int(time_limit) == time_limit: |
| 30 | + time_limit = int(time_limit) |
| 31 | + memory_limit = input( |
| 32 | + 'What is the memory limit (in MB) for "' + probname + '"? ') |
| 33 | + memory_limit = int(memory_limit) * 1024 * 1024 |
| 34 | + return { |
| 35 | + 'time-limit': time_limit, |
| 36 | + 'memory-limit': memory_limit, |
| 37 | + } |
| 38 | + |
| 39 | + |
| 40 | +def find_contestants(basedir): |
| 41 | + source_dir = os.path.join(basedir, 'source') |
| 42 | + contestants = [] |
| 43 | + for name in sorted(os.listdir(source_dir)): |
| 44 | + if os.path.isdir(os.path.join(source_dir, name)): |
| 45 | + contestants.append({ |
| 46 | + 'name': name, |
| 47 | + 'path': os.path.join('source', name), |
| 48 | + }) |
| 49 | + return contestants |
| 50 | + |
| 51 | + |
| 52 | +def find_testcases(basedir, probname): |
| 53 | + resource_limits = ask_resource_limits(probname) |
| 54 | + prob_dir = os.path.join(basedir, 'data', probname) |
| 55 | + has_in = {os.path.splitext(os.path.basename(x))[0] |
| 56 | + for x in glob(os.path.join(prob_dir, '*.in')) |
| 57 | + if os.path.isfile(x)} |
| 58 | + has_out = {os.path.splitext(os.path.basename(x))[0] |
| 59 | + for x in glob(os.path.join(prob_dir, '*.out')) |
| 60 | + if os.path.isfile(x)} |
| 61 | + testcases = [] |
| 62 | + prob_reldir = os.path.join('data', probname) |
| 63 | + for testdata in sorted(has_in & has_out): |
| 64 | + testcases.append({ |
| 65 | + 'input-file': os.path.join(prob_reldir, testdata + '.in'), |
| 66 | + 'output-file': os.path.join(prob_reldir, testdata + '.out'), |
| 67 | + 'resource-limits': resource_limits, |
| 68 | + }) |
| 69 | + if not testcases: |
| 70 | + return [] |
| 71 | + testcase_cnt = len(testcases) |
| 72 | + full_score_each = 100 // testcase_cnt |
| 73 | + for testcase in testcases: |
| 74 | + testcase['full-score'] = full_score_each |
| 75 | + return testcases |
| 76 | + |
| 77 | + |
| 78 | +def find_problems(basedir): |
| 79 | + data_dir = os.path.join(basedir, 'data') |
| 80 | + problems = [] |
| 81 | + for name in sorted(os.listdir(data_dir)): |
| 82 | + if os.path.isdir(os.path.join(data_dir, name)): |
| 83 | + testcases = find_testcases(basedir, name) |
| 84 | + problems.append({ |
| 85 | + 'type': 'normal', |
| 86 | + 'name': name, |
| 87 | + 'input-file': name + '.in', |
| 88 | + 'output-file': name + '.out', |
| 89 | + 'source-path': name, |
| 90 | + 'testcases': testcases, |
| 91 | + }) |
| 92 | + return problems |
| 93 | + |
| 94 | + |
| 95 | +def main(argv=None): |
| 96 | + if argv is None: |
| 97 | + argv = sys.argv[1:] |
| 98 | + args = docopt(__doc__, argv=argv) |
| 99 | + if os.path.exists(args['--contest']): |
| 100 | + if os.path.isdir(args['--contest']): |
| 101 | + print('Not overwriting directory.', file=sys.stderr) |
| 102 | + return 1 |
| 103 | + elif not args['--force']: |
| 104 | + print('Not overwriting existing file.', file=sys.stderr) |
| 105 | + return 1 |
| 106 | + cwd = os.getcwd() |
| 107 | + contest_data = { |
| 108 | + 'metadata': {'title': os.path.basename(cwd)}, |
| 109 | + 'contestants': find_contestants(cwd), |
| 110 | + 'problems': find_problems(cwd), |
| 111 | + } |
| 112 | + compiler_flags = {} |
| 113 | + if args['--cflags'] is not None: |
| 114 | + compiler_flags['c'] = args['--cflags'].strip() |
| 115 | + if args['--cxxflags'] is not None: |
| 116 | + compiler_flags['cpp'] = args['--cxxflags'].strip() |
| 117 | + if compiler_flags: |
| 118 | + for problem in contest_data['problems']: |
| 119 | + problem['compiler-flags'] = compiler_flags |
| 120 | + with open(args['--contest'], 'w') as fout: |
| 121 | + fout.write(yaml.safe_dump(contest_data)) |
0 commit comments