Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ornate Orbits #6

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open

Ornate Orbits #6

wants to merge 9 commits into from

Conversation

janine9vn
Copy link
Contributor

No description provided.

cin-lawrence and others added 9 commits July 19, 2024 00:49
* feat: add initial setup

* chore: remove watchdog from poetry
feat: add watch attr to docker-compose.yml
* Add random word generator using NLTK and WordNet

* Updated requirements.txt

* refactor: word generator

* chore: typing and nltk dependencies

* fix: ruff issues

* fix: Update is_valid method validation condtions

---------

Co-authored-by: Muktadir <[email protected]>
* add 3 slash command

add start-wordle for user to start the game

add guess for user to guess the word for now not fully function

add end-wordle for user to end the game

* feat: add db

* feat: add wordle logic

* feat: add db handling for wordle and guess

* feat: add wordle logic, ui and db request

* fix: should get the latest wordle game

* refactor: wordle game logic

* fix: any check using generator

* refactor: ui

* feat: update tests

* resolve merge conflict

* fix: KeyError when access guesses property, change order of select

* feat: add get_guesses function

* feat: update user interaction, bot embed message and DB operation

* fix: clear up unuse variable and debugging messages

* feat: add game end logic, valid word checking, bot response messages

* feat: add data set for 5 letters words

* fix: type consistency for some methods

* feat: update word gen to random by length

* feat: integrate wordle game with wordgen

* fix: stabilize current impl

* fix: should check for the word len first before validating

* fix: wrong package

* fix: should lower the word

* feat: bootstrap nltk on app load

* fix: get word from synset

* fix: should upper the generated word

* refactor: convert the functions into classes

* feat: integrate with the new ui classes

* refactor: resolve mypy issues

* refactor: use enums

* fix: missing self

* fix: ruff linting

* feat: add crawling scripts

* feat: update Dockerfile with trivia.db

* feat: add difficulty selection for the game

* fix: change the label for select ui

* fix: mypy complaints

* feat: add trivia question in between guesses

* refactor: typing

* refactor: guess method

* fix: reduce wordle retrievals

* feat: add player and repo

* feat: add player registration

* fix: player registration

* fix: game logic

* feat: add help command, remove jam command, add hint, change guess embed ui colour

* fix: wrong var

* fix: wrong pending condition

* fix: no hint for wrong answers

* fix: wrong condition

* fix: wrong condition check for status

* fix: wrong check

* fix: should end at last

* fix: change response message

* feat: add win stat

* fix: remove prints

* fix: ongoing condition

* feat: delete res

* fix: ruff

---------

Co-authored-by: unknown <[email protected]>
Co-authored-by: Bh <[email protected]>
* feat: update README

* fix: update styling

* fix: styling

* feat: add slide link
…c454c'

git-subtree-dir: ornate-orbits
git-subtree-mainline: 196cae3
git-subtree-split: a326407
Copy link

@ThirVondukr ThirVondukr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Project Structure

  • Project is neatly structured, but some things could be moved around a bit (e.g. I think that core/ui probably should belong to bot package/module)
  • Database operations are encapsulated in repository classes 👍
  • Cogs could be used instead of adding handlers directly to bot, but there's no problem with that at that scale

Code Quality

  • Transactions are not handled correctly, since multiple transactions could be ran during single operation.
  • Would be really great to make WordleGame independent from database, word generator (Really not sure if that's possible here since you don't just use it to generate words) and discord, so it would be a lot easier to test.
  • Some logic seems to be out of place, like calculating game status in the repository.

Testing

There's only one test case and I'd really like to see more, it's possible to even run the tests in a DB transaction if that's easier than abstracting or mocking everything.

Other

  • Mypy should probably be added to CI too, otherwise there's no guarantee that it's been run on the codebase when you're working in a team.

@@ -0,0 +1,13 @@
.PHONY: tc
tc:
@python -m mypy .

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be great to add Mypy to CI/Github Actions too

self.settings.GUILD_ID,
)
await bot.tree.sync(guild=Object(id=settings.GUILD_ID))
logger.warning("DONE syncing commands!")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably be logger.info, since syncing commands is a normal startup step


def __init__(self, settings: BotSettings) -> None:
self.settings = settings
super().__init__(settings.COMMAND_PREFIX, intents=Intents.default())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I'd subclass bot here, maybe just making a function would have been enough:
(You can also put additional startup code here, e.g. registering cogs)

def create_bot() -> Bot:
   settings = BotSettings()
   bot = Bot(settings.COMMAND_PREFIX, intents=Intents.default())
   
   @bot.event
   async def on_ready(self) -> None:
       pass
   
   return bot

name="start-wordle",
description="Start the wordle game",
guild=Object(id=settings.GUILD_ID),
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of making a global Bot instance you can use Cogs instead: https://discordpy.readthedocs.io/en/stable/ext/commands/cogs.html
That way when the bot code base gets larger you would have less problems

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EDIT: Since you're using commands, you probably need CommandTree instead: https://discordpy.readthedocs.io/en/stable/interactions/api.html?highlight=tree#discord.app_commands.CommandTree

await interaction.response.send_message("You are not in a game yet.")


async def trivial(interaction: Interaction[Client], wordle_id: UUID) -> None:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function name could probably be improved, e.g. show_trivial_question, judging from the docstring 😃

WORD_LENGTH_MAX: Final[int] = 15

WORD_AMOUNT_HARD: Final[int] = 1
WORD_AMOUNT_EASY: Final[int] = 5

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, would be create to have all of these fields as __init__ parameters instead, or as a part of different method signature. Also you can create a separate dataclass that would hold all that configuration to not overload the __init__:

@dataclasses.dataclass
class WordGeneratorConfig:
    corpora_wordnet: str = "corpora/wordnet"
    wordnet: str = "wordnet"

    word_length_min: int = 5
    word_length_max: int = 15
    word_amount_hard: int = 1
    word_amount_easy: int = 5
    

class WordGenerator:
    """The class for generating a random word between 5 to 10 chars."""

    def __init__(self, config: WordGeneratorConfig) -> None: ...


COPY ./app/ ./app/
COPY ./trivia.db ./trivia.db
COPY ./requirements-dev.txt .

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should copy and install all the dependencies before copying application code, otherwise changing anything in your ./app directory in that case would cause all the next layers to be invalidated, so your dependencies would have to be installed again.
I think it should look like this:

COPY ./requirements-dev.txt .

RUN pip install watchdog==4.0.1
RUN pip install -r requirements-dev.txt

COPY ./app/ ./app/
COPY ./trivia.db ./trivia.db

discord.py~=2.4.0
nltk~=3.8.1
sqlalchemy~=2.0.28
aiosqlite~=0.20.0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you have a pyproject.toml file it would be preferred to use that for declaring your dependencies, there's a lot of tools that work with it, e.g. poetry and pdm

@@ -0,0 +1,13 @@
[mypy]
ignore_missing_imports = true

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting this to true leads to mypy just ignoring incorrect imports (e.g. if you don't have such a file), so it would be better to set this to False.


COMMAND_PREFIX: Final[str] = os.getenv("COMMAND_PREFIX", "!@#")
DISCORD_TOKEN: Final[str] = os.environ["DISCORD_TOKEN"]
GUILD_ID: Final[str] = os.environ["GUILD_ID"]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be better to use pydantic-settings here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants