From 37671dd4d6893865730fea9bd07c9ef9ba375da6 Mon Sep 17 00:00:00 2001 From: Daniel Tsvetkov Date: Wed, 19 Jan 2022 01:43:19 +0100 Subject: [PATCH] almost solve web --- app.py | 102 ++++++++++++++++++++++++++++++++++++- templates/_guess_line.html | 5 ++ templates/game.html | 6 +-- templates/home.html | 3 +- templates/solve.html | 55 ++++++++++++++++++++ 5 files changed, 163 insertions(+), 8 deletions(-) create mode 100644 templates/_guess_line.html create mode 100644 templates/solve.html diff --git a/app.py b/app.py index 13f4210..09c95ac 100644 --- a/app.py +++ b/app.py @@ -4,8 +4,9 @@ from string import ascii_lowercase from flask import Flask, render_template, session, request, redirect, url_for, flash import sensitive -from lib import cat_words, ROUNDS, WORD_LENGTH +from lib import cat_words, ROUNDS, WORD_LENGTH, BLANK from play import build_non_letter_hint, build_letter_hint +from solve import first_round_words, round_words app = Flask(__name__) app.config['SECRET_KEY'] = sensitive.SECRET_KEY @@ -21,15 +22,26 @@ KEY_GAME_ID = 'game_id' KEY_GUESSES = 'guesses' KEY_GUESS = 'guess' KEY_STATE = 'state' +KEY_ROUND = 'round' +KEY_GUESSES_COLORS = 'guesses_colors' STATE_PLAYING = 'PLAYING' STATE_WIN = 'WIN' STATE_LOSE = 'LOSE' +COLOR_GREY_SHORT = '-' +COLOR_GREEN_SHORT = 'G' +COLOR_YELLOW_SHORT = 'Y' + COLOR_GREY = 'grey' COLOR_GREEN = 'green' COLOR_YELLOW = 'yellow' +COLOR_MAP = {COLOR_GREY_SHORT: COLOR_GREY, + COLOR_GREEN_SHORT: COLOR_GREEN, + COLOR_YELLOW_SHORT: COLOR_YELLOW, } +COLOR_MAP_REV = {w: k for k, w in COLOR_MAP.items()} + ERROR_GAME_ID_RANGE = "game_id must be between 0 and {}".format(NUM_GAMES) ERROR_NEED_WORD = 'Need a word' ERROR_GUESS_LENGTH = "Need {} letters.".format(WORD_LENGTH) @@ -160,7 +172,7 @@ def make_guess(): session[KEY_STATE] = STATE_LOSE if guess == word: session[KEY_STATE] = STATE_WIN - session[KEY_GUESSES] += '{}{}'.format(guess, GUESS_SPLITTER) + add_guess_to_session(guess) if KEY_GAME_ID not in session: flash(ERROR_NO_GAME) return redirect(url_for('home')) @@ -170,6 +182,92 @@ def make_guess(): return redirect(url_for('deterministic_game_id', game_id=game_id)) +def init_solve(): + session[KEY_GUESSES] = '' + session[KEY_ROUND] = 0 + session[KEY_GUESSES_COLORS] = COLOR_GREY_SHORT * WORD_LENGTH + GUESS_SPLITTER + + +def add_guess_to_session(guess): + session[KEY_GUESSES] += '{}{}'.format(guess, GUESS_SPLITTER) + + +@app.route('/init/solve') +def init_solve_game(): + init_solve() + return redirect(url_for('solve_game')) + + +def build_guess_colors(): + guesses = session[KEY_GUESSES].split(GUESS_SPLITTER) + guesses_colors = session.get(KEY_GUESSES_COLORS).split(GUESS_SPLITTER) + all_guesses = [] + for guess, guess_colors in zip(guesses, guesses_colors): + g = [] + for letter, color_id in zip(list(guess), list(guess_colors)): + g.append((letter, COLOR_MAP.get(color_id, COLOR_GREY))) + all_guesses.append(g) + return all_guesses[:-1] + + +def resolve_hints(): + all_non_letters, all_positional_letters, all_non_positional_letters = set(), [], [] + all_guesses = build_guess_colors() + for guess in all_guesses: + pos_letters, non_pos_letters = '', '' + for pos, letter_color in enumerate(guess): + letter, color = letter_color + if color == COLOR_GREY: + all_non_letters.add(letter) + pos_letters += BLANK + non_pos_letters += BLANK + elif color == COLOR_YELLOW: + pos_letters += BLANK + non_pos_letters += letter + elif color == COLOR_GREEN: + pos_letters += letter + non_pos_letters += BLANK + all_positional_letters.append(pos_letters) + all_non_positional_letters.append(non_pos_letters) + all_non_letters = ''.join(all_non_letters) + return all_non_letters, all_positional_letters, all_non_positional_letters + + +@app.route('/solve') +def solve_game(): + round_i = session[KEY_ROUND] + len_guesses = len(session[KEY_GUESSES].split(GUESS_SPLITTER)) - 1 + if len_guesses <= round_i: + if round_i == 0: + this_round_words = [w for w in first_round_words()] + else: + all_non_letters, all_positional_letters, all_non_positional_letters = resolve_hints() + this_round_words = [w for w in + round_words(all_non_letters, all_positional_letters, all_non_positional_letters)] + guess = random.choice(this_round_words) + add_guess_to_session(guess) + guesses = build_guess_colors() + return render_template('solve.html', guesses=guesses, WORD_LENGTH=WORD_LENGTH, + colors=[COLOR_GREY, COLOR_YELLOW, COLOR_GREEN]) + + +@app.route('/hint', methods=['post']) +def add_hint(): + letters_colors = [''] * WORD_LENGTH + for idx in range(WORD_LENGTH): + letters_colors[idx] = request.form.get("guess-letter-{}".format(idx)) + guess_colors = ''.join([COLOR_MAP_REV.get(letter_color) for letter_color in letters_colors]) + split_colors = session[KEY_GUESSES_COLORS].split(GUESS_SPLITTER) + if len(split_colors) >= 1: + # remove the last + session[KEY_GUESSES_COLORS] = GUESS_SPLITTER.join(split_colors[:-2]) + # TODO: there is some off by one here when adding the last guess_splitter (we need it to display a blank new guess) + session[KEY_GUESSES_COLORS] += guess_colors + GUESS_SPLITTER + \ + COLOR_GREY_SHORT * WORD_LENGTH + GUESS_SPLITTER + session[KEY_ROUND] += 1 + return redirect(url_for('solve_game')) + + def main(): app.run(debug=True) diff --git a/templates/_guess_line.html b/templates/_guess_line.html new file mode 100644 index 0000000..a4cc106 --- /dev/null +++ b/templates/_guess_line.html @@ -0,0 +1,5 @@ +
  • + {% for letter, color in guess %} + {{ letter|upper }} + {% endfor %} +
  • \ No newline at end of file diff --git a/templates/game.html b/templates/game.html index d7b4261..c483d80 100644 --- a/templates/game.html +++ b/templates/game.html @@ -4,11 +4,7 @@
    {% if state_playing %} diff --git a/templates/home.html b/templates/home.html index f438ed5..b94cea9 100644 --- a/templates/home.html +++ b/templates/home.html @@ -3,7 +3,8 @@ Random game
    - +
    +{#Solve game#} {% endblock %} \ No newline at end of file diff --git a/templates/solve.html b/templates/solve.html new file mode 100644 index 0000000..ba7e7cd --- /dev/null +++ b/templates/solve.html @@ -0,0 +1,55 @@ +{% include "layout.html" %} +{% block body %} + home +
    + + {% if state_playing %} +
    + + +
    + {% else %} +

    {{ state }}

    + {% endif %} +{% endblock %} \ No newline at end of file