def play(challenge, workspace, keys=None, diff=False): logger.info('play(...)') infile = os.path.join(workspace, 'in') if challenge.in_extension: infile += challenge.in_extension outfile = os.path.join(workspace, 'out') if challenge.out_extension: outfile += challenge.out_extension scriptfile = os.path.join(workspace, 'script') logfile = os.path.join(workspace, 'log') with open(outfile, 'w') as f: f.write(challenge.out_text) write('Launching vimgolf session', fg='yellow') main_loop( challenge=challenge, infile=infile, logfile=logfile, outfile=outfile, scriptfile=scriptfile, initial_keys=keys, diff=diff, ) write('Thanks for playing!', fg='green')
def put(challenge_id, keys, diff=False): challenge_id = expand_challenge_id(challenge_id) logger.info('put(%s)', challenge_id) if not validate_challenge_id(challenge_id): show_challenge_id_error() raise Failure() api_key = get_api_key() if not validate_api_key(api_key): write('An API key has not been configured', fg='red') write('Uploading to vimgolf.com is disabled', fg='red') show_api_key_help() if not confirm('Play without uploads?'): raise Failure() try: compliant = fetch_and_validate_challenge(challenge_id) except Failure: raise except Exception: logger.exception('challenge retrieval failed') write('The challenge retrieval has failed', err=True, fg='red') write('Please check the challenge ID on vimgolf.com', err=True, fg='red') raise Failure() challenge = Challenge(id=challenge_id, compliant=compliant, api_key=api_key).load() with tempfile.TemporaryDirectory() as d: play(challenge, d, keys=keys, diff=diff) challenge.update_metadata()
def inspect(challenge_id, keys, literal_lt, literal_gt): challenge_id = expand_challenge_id(challenge_id) logger.info('inspect(%s)', challenge_id) if not validate_challenge_id(challenge_id): show_challenge_id_error() raise Failure() try: challenge = Challenge(challenge_id) challenge.load_or_download() except Failure: raise except Exception: logger.exception('challenge retrieval failed') write('The challenge retrieval has failed', err=True, fg='red') write('Please check the challenge ID on vimgolf.com', err=True, fg='red') raise Failure() src_in_path = challenge.in_path name, ext = os.path.splitext(os.path.basename(src_in_path)) sequences = build_sequences( keys=keys, literal_gt=literal_gt, literal_lt=literal_lt ) with tempfile.TemporaryDirectory() as workspace: zfill = lambda s: str(s).zfill(3) def dst_path(index): return os.path.join(workspace, '{}{}{}'.format(name, zfill(index), ext)) def script_path(index): return os.path.join(workspace, 'mapping{}.vim'.format(zfill(index))) def in_path(index): return os.path.join(workspace, 'inspect-{}{}{}'.format(name, zfill(index), ext)) replay_sequences( dst_path=dst_path, script_path=script_path, sequences=sequences, src_in_path=src_in_path ) inspect_sequences( workspace=workspace, dst_path=dst_path, in_path=in_path, sequences=sequences )
def config(api_key=None): logger.info('config(...)') if api_key is not None and not validate_api_key(api_key): show_api_key_error() raise Failure() if api_key: set_api_key(api_key) else: api_key = get_api_key() if api_key: write(api_key) else: show_api_key_help()
def local(infile, outfile): logger.info('local(%s, %s)', infile, outfile) with open(infile, 'r') as f: in_text = format_(f.read()) with open(outfile, 'r') as f: out_text = format_(f.read()) _, in_extension = os.path.splitext(infile) _, out_extension = os.path.splitext(outfile) challenge = Challenge( in_text=in_text, out_text=out_text, in_extension=in_extension, out_extension=out_extension, id=None, ) with tempfile.TemporaryDirectory() as d: play(challenge, d)
def upload_result(challenge_id, api_key, raw_keys): logger.info('upload_result(...)') success = False try: url = urllib.parse.urljoin(GOLF_HOST, '/entry.json') data_dict = { 'challenge_id': challenge_id, 'apikey': api_key, 'entry': raw_keys, } data = urllib.parse.urlencode(data_dict).encode() response = http_request(url, data=data) message = json.loads(response.body) if message.get('status') == 'ok': success = True except Exception: logger.exception('upload failed') return success
def ls(incomplete=False, page=None, limit=LISTING_LIMIT): logger.info('list_(%s, %s)', page, limit) stored_challenges = get_stored_challenges() try: url = GOLF_HOST if page is not None: url = urllib.parse.urljoin(GOLF_HOST, '/?page={}'.format(page)) response = http_request(url) listings = extract_listings_from_page( page_html=response.body, limit=limit, stored_challenges=stored_challenges) except Failure: raise except Exception: logger.exception('challenge retrieval failed') write('The challenge list retrieval has failed', err=True, fg='red') raise Failure() table_rows = [['#', 'Name', 'Entries', 'ID', '⬆', 'Score', 'Answers']] for idx, listing in enumerate(listings): if incomplete and listing.uploaded: continue table_row = [ '{}{} '.format(EXPANSION_PREFIX, idx + 1), listing.name, listing.n_entries, style(listing.id, fg='yellow'), bool_to_mark(listing.uploaded), listing.score if listing.score and listing.score > 0 else '-', listing.answers or '-', ] table_rows.append(table_row) write(AsciiTable(table_rows).table) id_lookup = { str(idx + 1): listing.id for idx, listing in enumerate(listings) } set_id_lookup(id_lookup)
def show(challenge_id): challenge_id = expand_challenge_id(challenge_id) logger.info('show(%s)', challenge_id) if not validate_challenge_id(challenge_id): show_challenge_id_error() raise Failure() try: fetched = fetch_challenge_spec_and_page(challenge_id) challenge = fetched['challenge'] page_response = fetched['page'] page_url = fetched['url'] data = extract_data_from_page(page_response.body) name = data['name'] description = data['description'] leaders = data['leaders'] challenge.update_metadata(name, description) metadata = challenge.metadata start_file = challenge.in_text if not start_file.endswith('\n'): start_file += '\n' end_file = challenge.out_text if not end_file.endswith('\n'): end_file += '\n' separator = '-' * 50 write(separator) write('{} ('.format(name), nl=False) write(challenge_id, fg='yellow', nl=False) write(')') write(separator) write(page_url) write(separator) write('Leaderboard', fg='green') if leaders: for leader in leaders[:LEADER_LIMIT]: write('{} {}'.format(leader.username.ljust(15), leader.score)) if len(leaders) > LEADER_LIMIT: write('...') else: write('no entries yet', fg='yellow') write(separator) write(description) write(separator) write('Start File', fg='green') write(start_file, nl=False) write(separator) write('End File', fg='green') write(end_file, nl=False) write(separator) write('Stats', fg='green') write('Entered Solutions: {}'.format(metadata['answers'])) write('Uploaded: {}'.format(metadata['uploaded'])) write('Correct Solutions: {}'.format(metadata['correct'])) write('Self Best Score: {}'.format(metadata['best_score'])) answers = challenge.answers ignored_answer_suffix = 'ZQ' answer_rows = [['Keys', 'Correct', 'Submitted', 'Score', 'Timestamp']] for answer in answers: keys = ''.join(answer['keys']) if keys.endswith(ignored_answer_suffix): continue answer_row = [ keys, bool_to_mark(answer['correct']), bool_to_mark(answer['uploaded']), answer['score'], answer['timestamp'], ] answer_rows.append(answer_row) if len(answer_rows) > 1: write(AsciiTable(answer_rows).table) except Failure: raise except Exception: logger.exception('challenge retrieval failed') write('The challenge retrieval has failed', err=True, fg='red') write('Please check the challenge ID on vimgolf.com', err=True, fg='red') raise Failure()
def main(): setup_directories() init_logger() clean_stale_logs() logger.info('vimgolf started')