-
-
Save ecnerwala/ffc9b8c3f61e87ca043393a135d7794d to your computer and use it in GitHub Desktop.
| #!/usr/bin/env python3 | |
| """Download and setup problems from Competitive Companion | |
| Usage: | |
| download_prob.py --echo | |
| download_prob.py [<name>... | -n <number> | -b <batches> | --timeout <timeout>] [--dryrun] | |
| Options: | |
| -h --help Show this screen. | |
| --echo Just echo received responses and exit. | |
| --dryrun Don't actually create any problems | |
| Download limit options: | |
| -n COUNT, --number COUNT Number of problems. | |
| -b COUNT, --batches COUNT Number of batches. (Default 1 batch) | |
| -t TIME, --timeout TIME Timeout for listening to problems. in seconds | |
| """ | |
| from docopt import docopt | |
| import sys | |
| import http.server | |
| import json | |
| from pathlib import Path | |
| import subprocess | |
| import re | |
| # Returns unmarshalled or None | |
| def listen_once(*, timeout=None): | |
| json_data = None | |
| class CompetitiveCompanionHandler(http.server.BaseHTTPRequestHandler): | |
| def do_POST(self): | |
| nonlocal json_data | |
| json_data = json.load(self.rfile) | |
| with http.server.HTTPServer(('127.0.0.1', 10046), CompetitiveCompanionHandler) as server: | |
| server.timeout = timeout | |
| server.handle_request() | |
| if json_data is not None: | |
| print(f"Got data {json.dumps(json_data)}") | |
| else: | |
| print("Got no data") | |
| return json_data | |
| def listen_many(*, num_items=None, num_batches=None, timeout=None): | |
| if num_items is not None: | |
| res = [] | |
| for _ in range(num_items): | |
| cur = listen_once(timeout=None) | |
| res.append(cur) | |
| return res | |
| if num_batches is not None: | |
| res = [] | |
| batches = {} | |
| while len(batches) < num_batches or any(need for need, tot in batches.values()): | |
| print(f"Waiting for {num_batches} batches:", batches) | |
| cur = listen_once(timeout=None) | |
| res.append(cur) | |
| cur_batch = cur['batch'] | |
| batch_id = cur_batch['id'] | |
| batch_cnt = cur_batch['size'] | |
| if batch_id not in batches: | |
| batches[batch_id] = [batch_cnt, batch_cnt] | |
| assert batches[batch_id][0] > 0 | |
| batches[batch_id][0] -= 1 | |
| return res | |
| res = [listen_once(timeout=None)] | |
| while True: | |
| cnd = listen_once(timeout=timeout) | |
| if cnd is None: | |
| break | |
| res.append(cnd) | |
| return res | |
| NAME_PATTERN = re.compile(r'^(?:Problem )?([A-Z][0-9]*)\b') | |
| def get_prob_name(data): | |
| if 'USACO' in data['group']: | |
| if 'fileName' in data['input']: | |
| names = [data['input']['fileName'].rstrip('.in'), data['output']['fileName'].rstrip('.out')] | |
| if len(set(names)) == 1: | |
| return names[0] | |
| if 'url' in data and data['url'].startswith('https://www.codechef.com'): | |
| return data['url'].rstrip('/').rsplit('/')[-1] | |
| patternMatch = NAME_PATTERN.search(data['name']) | |
| if patternMatch is not None: | |
| return patternMatch.group(1) | |
| print(f"For data: {json.dumps(data, indent=2)}") | |
| return input("What name to give? ") | |
| def save_samples(data, prob_dir): | |
| with open(prob_dir / 'problem.json', 'w') as f: | |
| json.dump(data, f) | |
| for i, t in enumerate(data['tests'], start=1): | |
| with open(prob_dir / f'sample{i}.in', 'w') as f: | |
| f.write(t['input']) | |
| with open(prob_dir / f'sample{i}.out', 'w') as f: | |
| f.write(t['output']) | |
| # Providing name = '.' | |
| def make_prob(data, name=None): | |
| if name is None: | |
| name = get_prob_name(data) | |
| prob_dir = Path('.')/name | |
| if name == '.': | |
| print("Using current directory...") | |
| pass | |
| elif prob_dir.exists() and prob_dir.is_dir(): | |
| # Skip making it | |
| print(f"Already created problem {name}...") | |
| else: | |
| print(f"Creating problem {name}...") | |
| MAKE_PROB = Path(sys.path[0]) / 'make_prob.sh' | |
| try: | |
| subprocess.check_call([MAKE_PROB, name], stdout=sys.stdout, stderr=sys.stderr) | |
| except subprocess.CalledProcessError as e: | |
| print(f"Got error {e}") | |
| return | |
| print("Saving samples...") | |
| save_samples(data, prob_dir) | |
| print() | |
| def main(): | |
| arguments = docopt(__doc__) | |
| if arguments['--echo']: | |
| while True: | |
| print(listen_once()) | |
| else: | |
| dryrun = arguments['--dryrun'] | |
| def run_make_prob(*args, **kwargs): | |
| nonlocal dryrun | |
| if dryrun: | |
| print(f"make_prob(*args={args}, **kwargs={kwargs})") | |
| return | |
| make_prob(*args, **kwargs) | |
| if names := arguments['<name>']: | |
| datas = listen_many(num_items=len(names)) | |
| for data, name in zip(datas, names): | |
| run_make_prob(data, name) | |
| elif cnt := arguments['--number']: | |
| cnt = int(cnt) | |
| datas = listen_many(num_items=cnt) | |
| for data in datas: | |
| run_make_prob(data) | |
| elif batches := arguments['--batches']: | |
| batches = int(batches) | |
| datas = listen_many(num_batches=batches) | |
| for data in datas: | |
| run_make_prob(data) | |
| elif timeout := arguments['--timeout']: | |
| timeout = float(timeout) | |
| datas = listen_many(timeout=timeout) | |
| for data in datas: | |
| run_make_prob(data) | |
| else: | |
| datas = listen_many(num_batches=1) | |
| for data in datas: | |
| run_make_prob(data) | |
| if __name__ == '__main__': | |
| main() |
| #!/usr/bin/env bash | |
| DIR=$(dirname $0) | |
| search_up () | |
| ( | |
| while [[ $PWD != "/" ]]; do | |
| if [[ -e "$1" ]]; then | |
| pwd | |
| if [[ ! -e "$1/$2" ]]; then | |
| break | |
| fi | |
| fi | |
| cd .. | |
| done | |
| ) | |
| TEMPLATE_DIR='.template' | |
| PARENT_FILE='$PARENT' | |
| IFS=$'\n' | |
| TEMPLATE_DIRS=($(search_up "$TEMPLATE_DIR" "$PARENT_FILE" | tac)) | |
| unset IFS | |
| TEMPLATE_DIRS=(${TEMPLATE_DIRS[@]/%/\/"$TEMPLATE_DIR"}) | |
| if hash rename.ul 2>/dev/null; then | |
| RENAME=rename.ul | |
| else | |
| RENAME=rename | |
| fi | |
| for filepath in "$@"; do | |
| PROBLEM_NAME=$(basename "$filepath") | |
| if [[ -e "$filepath" ]]; then | |
| echo "$filepath already exists. Remove it and retry." | |
| continue | |
| fi | |
| # Copy files in | |
| mkdir -p "$filepath" | |
| for CURRENT_TEMPLATE_DIR in "${TEMPLATE_DIRS[@]}"; do | |
| cp -r -T "$CURRENT_TEMPLATE_DIR" "$filepath/" | |
| done | |
| rm -f "$filepath/$PARENT_FILE" | |
| # Rename PROBLEM_NAME in file names | |
| find $filepath -type f -print0 | xargs -0 ${RENAME} "\$PROBLEM_NAME" "$PROBLEM_NAME" | |
| # Envsubst PROBLEM_NAME in files | |
| export PROBLEM_NAME | |
| REPLACE_STRING='${PROBLEM_NAME}' | |
| find $filepath -type f -print0 | xargs -0 -I{} bash -c\ | |
| 'TEMP=$(mktemp) && cat "$1" > "$TEMP" && envsubst '"'$REPLACE_STRING'"' < "$TEMP" > "$1" && rm "$TEMP"'\ | |
| -- {} | |
| pushd $filepath > /dev/null | |
| if [[ -e "setup" ]]; then | |
| echo "Running setup" | |
| ./setup | |
| fi | |
| popd > /dev/null | |
| done |
For anyone with the same issue, add a new line after Usage ends. Here is the link where I found the solution:
https://stackoverflow.com/questions/31901138/docopt-on-python-3-only-prints-help-screen-and-does-not-execute-the-function
For anyone with the same issue, add a new line after Usage ends. Here is the link where I found the solution: https://stackoverflow.com/questions/31901138/docopt-on-python-3-only-prints-help-screen-and-does-not-execute-the-function
Huh, isn't there already a newline? Strange
For anyone with the same issue, add a new line after Usage ends. Here is the link where I found the solution: https://stackoverflow.com/questions/31901138/docopt-on-python-3-only-prints-help-screen-and-does-not-execute-the-function
Huh, isn't there already a newline? Strange
That is really strange. For some reason when I copied the contents of download_prob.py the newline after Usage was gone ...
Hm, that happens to me if I copy from this page (with syntax highlighting), but not if I copy from the Raw version. I guess there's some funny HTML/CSS going on. I guess that explains it then.
#ecnerwala can you share your setup file and the whole process how to setup nvim

It's just the newest one (0.6.2 I think).