Beispiel #1
0
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')
Beispiel #2
0
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()
Beispiel #3
0
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
        )
Beispiel #4
0
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()
Beispiel #5
0
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)
Beispiel #6
0
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
Beispiel #7
0
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)
Beispiel #8
0
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()
Beispiel #9
0
def main():
    setup_directories()
    init_logger()
    clean_stale_logs()
    logger.info('vimgolf started')