almost solve web
This commit is contained in:
parent
54ce23e7a5
commit
37671dd4d6
102
app.py
102
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)
|
||||
|
||||
|
5
templates/_guess_line.html
Normal file
5
templates/_guess_line.html
Normal file
@ -0,0 +1,5 @@
|
||||
<li>
|
||||
{% for letter, color in guess %}
|
||||
<span class="letter" style="color:{{ color }};">{{ letter|upper }}</span>
|
||||
{% endfor %}
|
||||
</li>
|
@ -4,11 +4,7 @@
|
||||
<hr>
|
||||
<ul>
|
||||
{% for guess in guesses %}
|
||||
<li>
|
||||
{% for letter, color in guess %}
|
||||
<span class="letter" style="color:{{ color }};">{{ letter|upper }}</span>
|
||||
{% endfor %}
|
||||
</li>
|
||||
{% include "_guess_line.html" %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if state_playing %}
|
||||
|
@ -3,7 +3,8 @@
|
||||
<a href="{{url_for('init_random_game')}}">Random game</a>
|
||||
<form method="post" action="{{url_for('init_deterministic_game')}}">
|
||||
<label>Deterministic (0 to {{ num_games }})</label>
|
||||
<input type="number" min="0" max="{{ num_games }}" name="{{ KEY_GAME_ID }}" autofocus/>
|
||||
<input type="number" min="0" max="{{ num_games }}" size="7" name="{{ KEY_GAME_ID }}" autofocus/>
|
||||
<input type="submit">
|
||||
</form>
|
||||
{#<a href="{{url_for('init_solve_game')}}">Solve game</a>#}
|
||||
{% endblock %}
|
55
templates/solve.html
Normal file
55
templates/solve.html
Normal file
@ -0,0 +1,55 @@
|
||||
{% include "layout.html" %}
|
||||
{% block body %}
|
||||
<a href="{{ url_for('home') }}">home</a>
|
||||
<hr>
|
||||
<ul>
|
||||
{% for guess in guesses %}
|
||||
{% if not loop.last %}
|
||||
{% include "_guess_line.html" %}
|
||||
{% else %}
|
||||
<form method="post" action="{{ url_for('add_hint') }}">
|
||||
<input type="hidden" name="guess" value="{{ guess }}">
|
||||
<table>
|
||||
<tr>
|
||||
{% for letter, color in guess %}
|
||||
<td>
|
||||
<span class="letter" style="color:{{ color }};">{{ letter|upper }}</span>
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% for color in colors %}
|
||||
<tr>
|
||||
{% for idx in range(WORD_LENGTH) %}
|
||||
<td>
|
||||
{% if guesses|length >= 2 and guesses[-1][idx][1] == colors[-1] %}
|
||||
<input type="hidden" name="guess-letter-{{ idx }}" value="{{ colors[-1] }}">
|
||||
{% else %}
|
||||
<label style="background-color:{{ color }};
|
||||
display: inline-block; height:30px; width:20px;"> </label>
|
||||
<input style="position: relative; left: -38px; top: -10px;"
|
||||
{% if color == colors[0] %}checked="checked"{% endif %}
|
||||
type="radio" name="guess-letter-{{ idx }}" value="{{ color }}">
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
<input type="submit">
|
||||
</form>
|
||||
</ul>
|
||||
{% if state_playing %}
|
||||
<form method="post" action="{{ url_for('make_guess') }}">
|
||||
<input maxlength="{{ WORD_LENGTH }}" minlength="{{ WORD_LENGTH }}" size="{{ WORD_LENGTH }}"
|
||||
name="{{ KEY_GUESS }}" autofocus autocomplete="off"
|
||||
style="text-transform:uppercase"/>
|
||||
<input type="submit">
|
||||
</form>
|
||||
{% else %}
|
||||
<p>{{ state }}</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
Loading…
Reference in New Issue
Block a user