-
-
Notifications
You must be signed in to change notification settings - Fork 0
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
base: main
Are you sure you want to change the base?
Conversation
* 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
There was a problem hiding this 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 tobot
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 . |
There was a problem hiding this comment.
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!") |
There was a problem hiding this comment.
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()) |
There was a problem hiding this comment.
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), | ||
) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 . |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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"] |
There was a problem hiding this comment.
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
No description provided.