6 Commits

6 changed files with 82 additions and 59 deletions

View File

@@ -2,35 +2,35 @@
# uv pip compile requirements-server.in # uv pip compile requirements-server.in
annotated-types==0.7.0 annotated-types==0.7.0
# via pydantic # via pydantic
anyio==4.7.0 anyio==4.11.0
# via # via
# httpx # httpx
# starlette # starlette
# watchfiles # watchfiles
certifi==2024.12.14 certifi==2025.8.3
# via # via
# httpcore # httpcore
# httpx # httpx
click==8.1.8 click==8.3.0
# via # via
# rich-toolkit # rich-toolkit
# typer # typer
# uvicorn # uvicorn
dnspython==2.7.0 dnspython==2.8.0
# via email-validator # via email-validator
email-validator==2.2.0 email-validator==2.3.0
# via fastapi # via fastapi
fastapi==0.115.6 fastapi==0.117.1
# via -r requirements.in # via -r requirements.in
fastapi-cli==0.0.7 fastapi-cli==0.0.13
# via fastapi # via fastapi
gunicorn==23.0.0 gunicorn==23.0.0
# via -r requirements-server.in # via -r requirements-server.in
h11==0.14.0 h11==0.16.0
# via # via
# httpcore # httpcore
# uvicorn # uvicorn
httpcore==1.0.7 httpcore==1.0.9
# via httpx # via httpx
httptools==0.6.4 httptools==0.6.4
# via uvicorn # via uvicorn
@@ -41,27 +41,27 @@ idna==3.10
# anyio # anyio
# email-validator # email-validator
# httpx # httpx
jinja2==3.1.5 jinja2==3.1.6
# via fastapi # via fastapi
markdown-it-py==3.0.0 markdown-it-py==4.0.0
# via rich # via rich
markupsafe==3.0.2 markupsafe==3.0.2
# via jinja2 # via jinja2
mdurl==0.1.2 mdurl==0.1.2
# via markdown-it-py # via markdown-it-py
packaging==24.2 packaging==25.0
# via gunicorn # via gunicorn
pydantic==2.10.4 pydantic==2.11.9
# via # via
# fastapi # fastapi
# pydantic-settings # pydantic-settings
pydantic-core==2.27.2 pydantic-core==2.33.2
# via pydantic # via pydantic
pydantic-settings==2.7.0 pydantic-settings==2.10.1
# via -r requirements.in # via -r requirements.in
pygments==2.18.0 pygments==2.19.2
# via rich # via rich
python-dotenv==1.0.1 python-dotenv==1.1.1
# via # via
# pydantic-settings # pydantic-settings
# uvicorn # uvicorn
@@ -69,35 +69,41 @@ python-multipart==0.0.20
# via fastapi # via fastapi
pyyaml==6.0.2 pyyaml==6.0.2
# via uvicorn # via uvicorn
rich==13.9.4 rich==14.1.0
# via # via
# rich-toolkit # rich-toolkit
# typer # typer
rich-toolkit==0.12.0 rich-toolkit==0.15.1
# via fastapi-cli # via fastapi-cli
shellingham==1.5.4 shellingham==1.5.4
# via typer # via typer
sniffio==1.3.1 sniffio==1.3.1
# via anyio # via anyio
starlette==0.41.3 starlette==0.48.0
# via fastapi # via fastapi
typer==0.15.1 typer==0.19.2
# via fastapi-cli # via fastapi-cli
typing-extensions==4.12.2 typing-extensions==4.15.0
# via # via
# anyio
# fastapi # fastapi
# pydantic # pydantic
# pydantic-core # pydantic-core
# rich-toolkit # rich-toolkit
# typer # typer
uvicorn==0.34.0 # typing-inspection
typing-inspection==0.4.1
# via
# pydantic
# pydantic-settings
unidecode==1.4.0
# via -r requirements.in
uvicorn==0.37.0
# via # via
# fastapi # fastapi
# fastapi-cli # fastapi-cli
uvloop==0.21.0 uvloop==0.21.0
# via uvicorn # via uvicorn
watchfiles==1.0.3 watchfiles==1.1.0
# via uvicorn # via uvicorn
websockets==14.1 websockets==15.0.1
# via uvicorn # via uvicorn

View File

@@ -1,2 +1,5 @@
fastapi[standard] fastapi[standard-no-fastapi-cloud-cli]
pydantic-settings pydantic-settings
# Normalise strings so we can compare without accents
unidecode

View File

@@ -2,33 +2,33 @@
# uv pip compile requirements.in # uv pip compile requirements.in
annotated-types==0.7.0 annotated-types==0.7.0
# via pydantic # via pydantic
anyio==4.7.0 anyio==4.11.0
# via # via
# httpx # httpx
# starlette # starlette
# watchfiles # watchfiles
certifi==2024.12.14 certifi==2025.8.3
# via # via
# httpcore # httpcore
# httpx # httpx
click==8.1.8 click==8.3.0
# via # via
# rich-toolkit # rich-toolkit
# typer # typer
# uvicorn # uvicorn
dnspython==2.7.0 dnspython==2.8.0
# via email-validator # via email-validator
email-validator==2.2.0 email-validator==2.3.0
# via fastapi # via fastapi
fastapi==0.115.6 fastapi==0.117.1
# via -r requirements.in # via -r requirements.in
fastapi-cli==0.0.7 fastapi-cli==0.0.13
# via fastapi # via fastapi
h11==0.14.0 h11==0.16.0
# via # via
# httpcore # httpcore
# uvicorn # uvicorn
httpcore==1.0.7 httpcore==1.0.9
# via httpx # via httpx
httptools==0.6.4 httptools==0.6.4
# via uvicorn # via uvicorn
@@ -39,25 +39,25 @@ idna==3.10
# anyio # anyio
# email-validator # email-validator
# httpx # httpx
jinja2==3.1.5 jinja2==3.1.6
# via fastapi # via fastapi
markdown-it-py==3.0.0 markdown-it-py==4.0.0
# via rich # via rich
markupsafe==3.0.2 markupsafe==3.0.2
# via jinja2 # via jinja2
mdurl==0.1.2 mdurl==0.1.2
# via markdown-it-py # via markdown-it-py
pydantic==2.10.4 pydantic==2.11.9
# via # via
# fastapi # fastapi
# pydantic-settings # pydantic-settings
pydantic-core==2.27.2 pydantic-core==2.33.2
# via pydantic # via pydantic
pydantic-settings==2.7.0 pydantic-settings==2.10.1
# via -r requirements.in # via -r requirements.in
pygments==2.18.0 pygments==2.19.2
# via rich # via rich
python-dotenv==1.0.1 python-dotenv==1.1.1
# via # via
# pydantic-settings # pydantic-settings
# uvicorn # uvicorn
@@ -65,35 +65,41 @@ python-multipart==0.0.20
# via fastapi # via fastapi
pyyaml==6.0.2 pyyaml==6.0.2
# via uvicorn # via uvicorn
rich==13.9.4 rich==14.1.0
# via # via
# rich-toolkit # rich-toolkit
# typer # typer
rich-toolkit==0.12.0 rich-toolkit==0.15.1
# via fastapi-cli # via fastapi-cli
shellingham==1.5.4 shellingham==1.5.4
# via typer # via typer
sniffio==1.3.1 sniffio==1.3.1
# via anyio # via anyio
starlette==0.41.3 starlette==0.48.0
# via fastapi # via fastapi
typer==0.15.1 typer==0.19.2
# via fastapi-cli # via fastapi-cli
typing-extensions==4.12.2 typing-extensions==4.15.0
# via # via
# anyio
# fastapi # fastapi
# pydantic # pydantic
# pydantic-core # pydantic-core
# rich-toolkit # rich-toolkit
# typer # typer
uvicorn==0.34.0 # typing-inspection
typing-inspection==0.4.1
# via
# pydantic
# pydantic-settings
unidecode==1.4.0
# via -r requirements.in
uvicorn==0.37.0
# via # via
# fastapi # fastapi
# fastapi-cli # fastapi-cli
uvloop==0.21.0 uvloop==0.21.0
# via uvicorn # via uvicorn
watchfiles==1.0.3 watchfiles==1.1.0
# via uvicorn # via uvicorn
websockets==14.1 websockets==15.0.1
# via uvicorn # via uvicorn

View File

@@ -10,9 +10,9 @@ from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from pydantic import DirectoryPath, FilePath from pydantic import DirectoryPath, FilePath
from pydantic_settings import BaseSettings from pydantic_settings import BaseSettings
from unidecode import unidecode
VERSION = '0.3.3'
VERSION = '0.3.1'
AMSTERDAM = ZoneInfo('Europe/Amsterdam') AMSTERDAM = ZoneInfo('Europe/Amsterdam')
@@ -100,9 +100,9 @@ def handle_guess(word: Union[str, None] = None):
return {'error': 'Word not in dictionary'} return {'error': 'Word not in dictionary'}
hint = 'it' hint = 'it'
if word_of_the_day < word: if word_of_the_day < unidecode(word):
hint = 'before' hint = 'before'
if word_of_the_day > word: if word_of_the_day > unidecode(word):
hint = 'after' hint = 'after'
logger.info('Guess: %s for game %d (%s), goal is %s', word, current_game_id, word_of_the_day, hint) logger.info('Guess: %s for game %d (%s), goal is %s', word, current_game_id, word_of_the_day, hint)

View File

@@ -39,6 +39,7 @@ a.title {
.guessesheading, .guessesbefore, .guessesafter { .guessesheading, .guessesbefore, .guessesafter {
text-align: center; text-align: center;
clear: both;
} }
input[type="text"] { input[type="text"] {

View File

@@ -30,7 +30,7 @@ document.addEventListener('alpine:init', () => {
/** Initialise the application after loading */ /** Initialise the application after loading */
await this.getGameID(); await this.getGameID();
setInterval(() => { setInterval(() => {
// Update counter to next game (midnight UTC, fetched from API) every second // Update counter to the next game (midnight UTC, fetched from API) every second
this.countDownTimer(); this.countDownTimer();
}, 1000); }, 1000);
}, },
@@ -58,7 +58,7 @@ document.addEventListener('alpine:init', () => {
/** Handle the newly entered guess */ /** Handle the newly entered guess */
this.guessError = null; this.guessError = null;
/* Normalise on lowercase, and strip whitespace from begin and end, just in case */ /* Normalise on lowercase, and strip whitespace from start and end, just in case */
this.guessValue = this.guessValue.toLowerCase().trim(); this.guessValue = this.guessValue.toLowerCase().trim();
if (this.guessValue === '') { if (this.guessValue === '') {
@@ -132,7 +132,7 @@ document.addEventListener('alpine:init', () => {
this.resultTimeTaken = ''; this.resultTimeTaken = '';
}, },
getFormattedTime(milliseconds) { getFormattedTime(milliseconds) {
/** Nicely format time for 'time played' */ /** Format the time for 'time played' nicely */
if (!Number.isInteger(milliseconds)) { if (!Number.isInteger(milliseconds)) {
return ''; return '';
} }
@@ -195,3 +195,10 @@ document.addEventListener('alpine:init', () => {
/* On AlpineJS completely loaded, do all this */ /* On AlpineJS completely loaded, do all this */
// Alpine.store('alfagok').getGameID(); // Alpine.store('alfagok').getGameID();
// }) // })
document.onvisibilitychange = () => {
if (!document.hidden) {
/* Tab/window is shown again, possibly after a long time, check if game is still current, otherwise re-load */
Alpine.store('alfagok').getGameID();
}
};