Fix wordle code

pull/129/head
stijndcl 2022-08-29 20:49:29 +02:00
parent 8a4baf6bb8
commit 73d44de46e
11 changed files with 58 additions and 48 deletions

View File

@ -17,7 +17,7 @@ async def add_birthday(session: AsyncSession, user_id: int, birthday: date):
If already present, overwrites the existing one If already present, overwrites the existing one
""" """
user = await users.get_or_add(session, user_id, options=[selectinload(User.birthday)]) user = await users.get_or_add_user(session, user_id, options=[selectinload(User.birthday)])
if user.birthday is not None: if user.birthday is not None:
bd = user.birthday bd = user.birthday

View File

@ -29,13 +29,13 @@ NIGHTLY_AMOUNT = 420
async def get_bank(session: AsyncSession, user_id: int) -> Bank: async def get_bank(session: AsyncSession, user_id: int) -> Bank:
"""Get a user's bank info""" """Get a user's bank info"""
user = await users.get_or_add(session, user_id) user = await users.get_or_add_user(session, user_id)
return user.bank return user.bank
async def get_nightly_data(session: AsyncSession, user_id: int) -> NightlyData: async def get_nightly_data(session: AsyncSession, user_id: int) -> NightlyData:
"""Get a user's nightly info""" """Get a user's nightly info"""
user = await users.get_or_add(session, user_id) user = await users.get_or_add_user(session, user_id)
return user.nightly_data return user.nightly_data

View File

@ -6,11 +6,11 @@ from sqlalchemy.ext.asyncio import AsyncSession
from database.schemas import Bank, NightlyData, User from database.schemas import Bank, NightlyData, User
__all__ = [ __all__ = [
"get_or_add", "get_or_add_user",
] ]
async def get_or_add(session: AsyncSession, user_id: int, *, options: Optional[list] = None) -> User: async def get_or_add_user(session: AsyncSession, user_id: int, *, options: Optional[list] = None) -> User:
"""Get a user's profile """Get a user's profile
If it doesn't exist yet, create it (along with all linked datastructures) If it doesn't exist yet, create it (along with all linked datastructures)

View File

@ -4,6 +4,7 @@ from typing import Optional
from sqlalchemy import delete, select from sqlalchemy import delete, select
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from database.crud.users import get_or_add_user
from database.schemas import WordleGuess, WordleWord from database.schemas import WordleGuess, WordleWord
__all__ = [ __all__ = [
@ -16,6 +17,7 @@ __all__ = [
async def get_active_wordle_game(session: AsyncSession, user_id: int) -> list[WordleGuess]: async def get_active_wordle_game(session: AsyncSession, user_id: int) -> list[WordleGuess]:
"""Find a player's active game""" """Find a player's active game"""
await get_or_add_user(session, user_id)
statement = select(WordleGuess).where(WordleGuess.user_id == user_id) statement = select(WordleGuess).where(WordleGuess.user_id == user_id)
guesses = (await session.execute(statement)).scalars().all() guesses = (await session.execute(statement)).scalars().all()
return guesses return guesses

View File

@ -121,7 +121,7 @@ class WordleCache(DatabaseCache):
async def invalidate(self, database_session: AsyncSession): async def invalidate(self, database_session: AsyncSession):
word = await wordle.get_daily_word(database_session) word = await wordle.get_daily_word(database_session)
if word is not None: if word is not None:
self.data = [word] self.data = [word.word]
class CacheManager: class CacheManager:

View File

@ -5,11 +5,7 @@ from discord import app_commands
from discord.ext import commands from discord.ext import commands
from database.constants import WORDLE_GUESS_COUNT, WORDLE_WORD_LENGTH from database.constants import WORDLE_GUESS_COUNT, WORDLE_WORD_LENGTH
from database.crud.wordle import ( from database.crud.wordle import get_active_wordle_game, make_wordle_guess
get_active_wordle_game,
make_wordle_guess,
start_new_wordle_game,
)
from didier import Didier from didier import Didier
from didier.data.embeds.wordle import WordleEmbed, WordleErrorEmbed from didier.data.embeds.wordle import WordleEmbed, WordleErrorEmbed
@ -35,31 +31,35 @@ class Games(commands.Cog):
embed = WordleErrorEmbed(message=f"Guess must be 5 characters, but `{guess}` is {len(guess)}.").to_embed() embed = WordleErrorEmbed(message=f"Guess must be 5 characters, but `{guess}` is {len(guess)}.").to_embed()
return await interaction.followup.send(embed=embed) return await interaction.followup.send(embed=embed)
active_game = await get_active_wordle_game(self.client.mongo_db, interaction.user.id) word = self.client.database_caches.wordle_word.data[0].lower()
if active_game is None:
active_game = await start_new_wordle_game(self.client.mongo_db, interaction.user.id)
# Trying to guess with a complete game async with self.client.postgres_session as session:
if len(active_game.guesses) == WORDLE_GUESS_COUNT and guess: guesses_instances = await get_active_wordle_game(session, interaction.user.id)
embed = WordleErrorEmbed(message="You've already completed today's Wordle.\nTry again tomorrow!").to_embed() guesses = list(map(lambda g: g.guess, guesses_instances))
return await interaction.followup.send(embed=embed)
# Make a guess # Trying to guess with a complete game
if guess: if (len(guesses) == WORDLE_GUESS_COUNT and guess) or word in guesses:
# The guess is not a real word embed = WordleErrorEmbed(
if guess.lower() not in self.client.wordle_words: message="You've already completed today's Wordle.\nTry again tomorrow!"
embed = WordleErrorEmbed(message=f"`{guess}` is not a valid word.").to_embed() ).to_embed()
return await interaction.followup.send(embed=embed) return await interaction.followup.send(embed=embed)
guess = guess.lower() # Make a guess
await make_wordle_guess(self.client.mongo_db, interaction.user.id, guess) if guess:
# The guess is not a real word
if guess.lower() not in self.client.wordle_words:
embed = WordleErrorEmbed(message=f"`{guess}` is not a valid word.").to_embed()
return await interaction.followup.send(embed=embed)
# Don't re-request the game, we already have it guess = guess.lower()
# just append locally await make_wordle_guess(session, interaction.user.id, guess)
active_game.guesses.append(guess)
embed = WordleEmbed(game=active_game, word=self.client.database_caches.wordle_word.data[0]).to_embed() # Don't re-request the game, we already have it
await interaction.followup.send(embed=embed) # just append locally
guesses.append(guess)
embed = WordleEmbed(guesses=guesses, word=word).to_embed()
await interaction.followup.send(embed=embed)
async def setup(client: Didier): async def setup(client: Didier):

View File

@ -140,9 +140,9 @@ class Tasks(commands.Cog):
@tasks.loop(time=DAILY_RESET_TIME) @tasks.loop(time=DAILY_RESET_TIME)
async def reset_wordle_word(self, forced: bool = False): async def reset_wordle_word(self, forced: bool = False):
"""Reset the daily Wordle word""" """Reset the daily Wordle word"""
db = self.client.mongo_db async with self.client.postgres_session as session:
word = await set_daily_word(db, random.choice(tuple(self.client.wordle_words)), forced=forced) word = await set_daily_word(session, random.choice(tuple(self.client.wordle_words)), forced=forced)
self.client.database_caches.wordle_word.data = [word] self.client.database_caches.wordle_word.data = [word]
@reset_wordle_word.before_loop @reset_wordle_word.before_loop
async def _before_reset_wordle_word(self): async def _before_reset_wordle_word(self):

View File

@ -1,12 +1,11 @@
import enum import enum
from dataclasses import dataclass from dataclasses import dataclass
from typing import Optional
import discord import discord
from overrides import overrides from overrides import overrides
from database.constants import WORDLE_GUESS_COUNT, WORDLE_WORD_LENGTH from database.constants import WORDLE_GUESS_COUNT, WORDLE_WORD_LENGTH
from database.schemas.mongo.wordle import WordleGame from database.schemas import WordleGuess
from didier.data.embeds.base import EmbedBaseModel from didier.data.embeds.base import EmbedBaseModel
from didier.utils.types.datetime import int_to_weekday, tz_aware_now from didier.utils.types.datetime import int_to_weekday, tz_aware_now
@ -32,7 +31,7 @@ class WordleColour(enum.IntEnum):
class WordleEmbed(EmbedBaseModel): class WordleEmbed(EmbedBaseModel):
"""Embed for a Wordle game""" """Embed for a Wordle game"""
game: Optional[WordleGame] guesses: list[WordleGuess]
word: str word: str
def _letter_colour(self, guess: str, index: int) -> WordleColour: def _letter_colour(self, guess: str, index: int) -> WordleColour:
@ -68,9 +67,8 @@ class WordleEmbed(EmbedBaseModel):
colours = [] colours = []
# Add all the guesses # Add all the guesses
if self.game is not None: for guess in self.guesses:
for guess in self.game.guesses: colours.append(self._guess_colours(guess))
colours.append(self._guess_colours(guess))
# Fill the rest with empty spots # Fill the rest with empty spots
for _ in range(WORDLE_GUESS_COUNT - len(colours)): for _ in range(WORDLE_GUESS_COUNT - len(colours)):
@ -93,6 +91,16 @@ class WordleEmbed(EmbedBaseModel):
return emojis return emojis
def _is_game_over(self) -> bool:
"""Check if the current game is over or not"""
if not self.guesses:
return False
if len(self.guesses) == WORDLE_GUESS_COUNT:
return True
return self.word.lower() in self.guesses
@overrides @overrides
def to_embed(self, **kwargs) -> discord.Embed: def to_embed(self, **kwargs) -> discord.Embed:
only_colours = kwargs.get("only_colours", False) only_colours = kwargs.get("only_colours", False)
@ -105,12 +113,12 @@ class WordleEmbed(EmbedBaseModel):
rows = [" ".join(row) for row in emojis] rows = [" ".join(row) for row in emojis]
# Don't reveal anything if we only want to show the colours # Don't reveal anything if we only want to show the colours
if not only_colours and self.game is not None: if not only_colours and self.guesses:
for i, guess in enumerate(self.game.guesses): for i, guess in enumerate(self.guesses):
rows[i] += f" ||{guess.upper()}||" rows[i] += f" ||{guess.upper()}||"
# If the game is over, reveal the word # If the game is over, reveal the word
if self.game.is_game_over(self.word): if self._is_game_over():
rows.append(f"\n\nThe word was **{self.word.upper()}**!") rows.append(f"\n\nThe word was **{self.word.upper()}**!")
embed.description = "\n\n".join(rows) embed.description = "\n\n".join(rows)

View File

@ -25,7 +25,7 @@ def test_user_id() -> int:
@pytest.fixture @pytest.fixture
async def user(postgres: AsyncSession, test_user_id: int) -> User: async def user(postgres: AsyncSession, test_user_id: int) -> User:
"""Fixture to create a user""" """Fixture to create a user"""
_user = await users.get_or_add(postgres, test_user_id) _user = await users.get_or_add_user(postgres, test_user_id)
await postgres.refresh(_user) await postgres.refresh(_user)
return _user return _user

View File

@ -54,7 +54,7 @@ async def test_get_birthdays_on_day(postgres: AsyncSession, user: User):
"""Test getting all birthdays on a given day""" """Test getting all birthdays on a given day"""
await crud.add_birthday(postgres, user.user_id, datetime.today().replace(year=2001)) await crud.add_birthday(postgres, user.user_id, datetime.today().replace(year=2001))
user_2 = await users.get_or_add(postgres, user.user_id + 1) user_2 = await users.get_or_add_user(postgres, user.user_id + 1)
await crud.add_birthday(postgres, user_2.user_id, datetime.today() + timedelta(weeks=1)) await crud.add_birthday(postgres, user_2.user_id, datetime.today() + timedelta(weeks=1))
birthdays = await crud.get_birthdays_on_day(postgres, datetime.today()) birthdays = await crud.get_birthdays_on_day(postgres, datetime.today())
assert len(birthdays) == 1 assert len(birthdays) == 1

View File

@ -7,7 +7,7 @@ from database.schemas import User
async def test_get_or_add_non_existing(postgres: AsyncSession): async def test_get_or_add_non_existing(postgres: AsyncSession):
"""Test get_or_add for a user that doesn't exist""" """Test get_or_add for a user that doesn't exist"""
await crud.get_or_add(postgres, 1) await crud.get_or_add_user(postgres, 1)
statement = select(User) statement = select(User)
res = (await postgres.execute(statement)).scalars().all() res = (await postgres.execute(statement)).scalars().all()
@ -18,8 +18,8 @@ async def test_get_or_add_non_existing(postgres: AsyncSession):
async def test_get_or_add_existing(postgres: AsyncSession): async def test_get_or_add_existing(postgres: AsyncSession):
"""Test get_or_add for a user that does exist""" """Test get_or_add for a user that does exist"""
user = await crud.get_or_add(postgres, 1) user = await crud.get_or_add_user(postgres, 1)
bank = user.bank bank = user.bank
assert await crud.get_or_add(postgres, 1) == user assert await crud.get_or_add_user(postgres, 1) == user
assert (await crud.get_or_add(postgres, 1)).bank == bank assert (await crud.get_or_add_user(postgres, 1)).bank == bank