-
-
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 |
maybe should i add download_prob and make_prob to the path ?
Ok,
Which version of python are you using?
3.8.3
No,
Thats not necessary you can just change the permissions and run it via the shell
Oh, so try to upgrade your python
Hey still the same problem :(
**_Got data {"name": "A. Avoid Trygub", "group": "Codeforces - Codeforces Global Round 12", "url": "https://codeforces.com/contest/1450/problem/A", "interactive": false, "memoryLimit": 256, "timeLimit": 1000, "tests": [{"input": "3\n11\nantontrygub\n15\nbestcoordinator\n19\ntrywatchinggurabruh\n", "output": "bugyrtnotna\nbestcoordinator\nbruhtrywatchinggura\n"}], "testType": "single", "input": {"type": "stdin"}, "output": {"type": "stdout"}, "languages": {"java": {"mainClass": "Main", "taskClass": "AAvoidTrygub"}}}
Creating problem n3...
Traceback (most recent call last):
File "C:\Users\admin\Downloads\ffc9b8c3f61e87ca043393a135d7794d-60857c014aa8f76ec654d8dccbcca81f426ef3cc\ffc9b8c3f61e87ca043393a135d7794d-60857c014aa8f76ec654d8dccbcca81f426ef3cc\download_prob.py", line 130, in
main()
File "C:\Users\admin\Downloads\ffc9b8c3f61e87ca043393a135d7794d-60857c014aa8f76ec654d8dccbcca81f426ef3cc\ffc9b8c3f61e87ca043393a135d7794d-60857c014aa8f76ec654d8dccbcca81f426ef3cc\download_prob.py", line 115, in main
make_prob(data, name)
File "C:\Users\admin\Downloads\ffc9b8c3f61e87ca043393a135d7794d-60857c014aa8f76ec654d8dccbcca81f426ef3cc\ffc9b8c3f61e87ca043393a135d7794d-60857c014aa8f76ec654d8dccbcca81f426ef3cc\download_prob.py", line 88, in make_prob
subprocess.check_call([MAKE_PROB, name], stdout=sys.stdout, stderr=sys.stderr)
File "C:\Users\admin\AppData\Local\Programs\Python\Python39\lib\subprocess.py", line 368, in check_call
retcode = call(*popenargs, **kwargs)
File "C:\Users\admin\AppData\Local\Programs\Python\Python39\lib\subprocess.py", line 349, in call
with Popen(*popenargs, kwargs) as p:
File "C:\Users\admin\AppData\Local\Programs\Python\Python39\lib\subprocess.py", line 947, in init
self._execute_child(args, executable, preexec_fn, close_fds,
File "C:\Users\admin\AppData\Local\Programs\Python\Python39\lib\subprocess.py", line 1416, in _execute_child
hp, ht, pid, tid = winapi.CreateProcess(executable, args,
and this
OSError: [WinError 193] %1 is not a valid Win32 application
@BryanMauricio you can try WSL
and this
OSError: [WinError 193] %1 is not a valid Win32 application
download_prob.py is meant to be run on a linux system. However if you are using a windows system (like me).. You can install Windows Subsystem for Linux. Link for reference - https://docs.microsoft.com/en-us/windows/wsl/install-win10
Then install Ubuntu or any other distro via microsoft store.
After doing all this.....
- Install Competitive Companion and change port to 10046.
- Open Cmd and run the command "wsl"
- navigate to your folder where u have your download_prob.py script.
- run the script with python3 ./download_prob.py and click on the green plus.
- Get back with any questions if you face any problem
I faced this error but i do all things, what is a problem ?
Got data {"name": "C. Peaceful Rooks", "group": "Codeforces - Codeforces Round #692 (Div. 2, based on Technocup 2021 Elimination Round 3)", "url": "https://codeforces.com/contest/1465/problem/C", "interactive": false, "memoryLimit": 256, "timeLimit": 1000, "tests": [{"input": "4\n3 1\n2 3\n3 2\n2 1\n1 2\n5 3\n2 3\n3 1\n1 2\n5 4\n4 5\n5 1\n2 2\n3 3\n", "output": "1\n3\n4\n2\n"}], "testType": "single", "input": {"type": "stdin"}, "output": {"type": "stdout"}, "languages": {"java": {"mainClass": "Main", "taskClass": "CPeacefulRooks"}}} Creating problem a... Traceback (most recent call last): File "/home/laniakea/programming/download_prob.py", line 130, in <module> main() File "/home/laniakea/programming/download_prob.py", line 115, in main make_prob(data, name) File "/home/laniakea/programming/download_prob.py", line 88, in make_prob subprocess.check_call([MAKE_PROB, name], stdout=sys.stdout, stderr=sys.stderr) File "/usr/lib/python3.8/subprocess.py", line 359, in check_call retcode = call(*popenargs, **kwargs) File "/usr/lib/python3.8/subprocess.py", line 340, in call with Popen(*popenargs, **kwargs) as p: File "/usr/lib/python3.8/subprocess.py", line 854, in __init__ self._execute_child(args, executable, preexec_fn, close_fds, File "/usr/lib/python3.8/subprocess.py", line 1702, in _execute_child raise child_exception_type(errno_num, err_msg, err_filename) PermissionError: [Errno 13] Permission denied: PosixPath('/home/laniakea/programming/make_prob.sh')
Try this :
- Run sudo python3 download_prob.py -n6 (and get all problems) --> Do this in WSL
- If that dosen't work... run chmod +x download_prob.py --> Do this in WSL
- Make sure you have the .template directory, make_prob.sh, download_prob.py in the same folder.. Eg -> Have them all in yr programming directory.
- Close the file in the python IDLE and then run the program
- Get back with any questions if you face any problem
Thank you for the script! I will build my own using it! :-)
how to use it in linux
please help me.....
Do the same thing but in terminal
I faced this error but i do all things, what is a problem ?
Got data {"name": "C. Peaceful Rooks", "group": "Codeforces - Codeforces Round #692 (Div. 2, based on Technocup 2021 Elimination Round 3)", "url": "https://codeforces.com/contest/1465/problem/C", "interactive": false, "memoryLimit": 256, "timeLimit": 1000, "tests": [{"input": "4\n3 1\n2 3\n3 2\n2 1\n1 2\n5 3\n2 3\n3 1\n1 2\n5 4\n4 5\n5 1\n2 2\n3 3\n", "output": "1\n3\n4\n2\n"}], "testType": "single", "input": {"type": "stdin"}, "output": {"type": "stdout"}, "languages": {"java": {"mainClass": "Main", "taskClass": "CPeacefulRooks"}}} Creating problem a... Traceback (most recent call last): File "/home/laniakea/programming/download_prob.py", line 130, in <module> main() File "/home/laniakea/programming/download_prob.py", line 115, in main make_prob(data, name) File "/home/laniakea/programming/download_prob.py", line 88, in make_prob subprocess.check_call([MAKE_PROB, name], stdout=sys.stdout, stderr=sys.stderr) File "/usr/lib/python3.8/subprocess.py", line 359, in check_call retcode = call(*popenargs, **kwargs) File "/usr/lib/python3.8/subprocess.py", line 340, in call with Popen(*popenargs, **kwargs) as p: File "/usr/lib/python3.8/subprocess.py", line 854, in __init__ self._execute_child(args, executable, preexec_fn, close_fds, File "/usr/lib/python3.8/subprocess.py", line 1702, in _execute_child raise child_exception_type(errno_num, err_msg, err_filename) PermissionError: [Errno 13] Permission denied: PosixPath('/home/laniakea/programming/make_prob.sh')
Hey,
Even I faced this error on a new computer.
run : chmod +x make_prob.sh
run : chmod +x download_prob.py
I didn't get the settings of :make!test. How can i do this?
You can do it as it is simply a python script
Hey
Could you help me with an error
I tried debugging myself but there's one error still left
Global symbol "$PROBLEM_NAME" requires explicit package name (did you forget to declare "my $PROBLEM_NAME"?) at (user-supplied code) line 3.
xargs: rename: exited with status 255; aborting
Also, I've to manually copy the Makefile and $PROBLEM_NAME.cpp to the problem directory and then make changes to problem name section in the Makefile
It can work as desired if the above errors are removed.
Any clue to make it work ?
Appreciate your time
Nevermind
I made it work by using cat
, echo
and sed
commands instead of the lines 46-54
in make_prob.sh
cat ~/programming/template.cpp > ./$filepath/"$PROBLEM_NAME".cpp; echo "created '$PROBLEM_NAME'.cpp file"; cp ~/programming/Makefile ./$filepath/; sed -i '1s/^/PROBLEM_NAME := '$PROBLEM_NAME'\n/' ./$filepath/Makefile;
I'm adding my make_prob.sh here, in case anyone finds it useful
#!/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"
cat ~/programming/template.cpp > ./$filepath/"$PROBLEM_NAME".cpp; echo "created '$PROBLEM_NAME'.cpp file"; cp ~/programming/Makefile ./$filepath/; sed -i '1s/^/PROBLEM_NAME := '$PROBLEM_NAME'\n/' ./$filepath/Makefile;
pushd $filepath > /dev/null
if [[ -e "setup" ]]; then
./setup
fi
popd > /dev/null
done
Hi there, I'm confused by $PARENT since it's empty in mac. What exact meaning it is? Is it the folder name like "Codeforces 746"?
Very weird, someone else reported something like that too. I verified that it's the same code as on my computer, so I'm not sure what the difference is. Maybe there's something with docopt versions or something? (By the way, the right usage is ./download_prob.py A B C
to download 3 problems named A B C)
Excuse me, docopt version to install? I tried it on a Mac but it gives me the same error, I think my docopt version is wrong.
It's just the newest one (0.6.2 I think).
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
cmd