-
-
Notifications
You must be signed in to change notification settings - Fork 0
Grand Gardenias #19
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
base: main
Are you sure you want to change the base?
Grand Gardenias #19
Conversation
warm-up: add my name to README
warm-up: add my name to README
The commit fixes the issue of being unable to use 'poetry add' command, and also adds the pyscript package
Fixes poetry.lock and adds pyscript
Create a base framework for the app
* Randomises the block spawn position This decision is for making the game, more lively by changing the start position of the block, and introduces a bit of luck * Fixes linting issues of poetry.lock In the last commit to main there was some linting issue in the poetry.lock file, which have been fixed using the following command :- pre-commit run --all-files * Adding option to move the block from down arrow This decision has been made to give more control to the player in making the game faster if they desire to do so * Update main.py * Update main.py --------- Co-authored-by: Zishan Kadri <[email protected]>
Introduced a modular code structure for the PyScript application by moving reusable components into the src/ package. Configured <py-config> to preload all modules from src/ and src/assets/ into the browser's virtual filesystem so they can be imported normally. This change allows: - Cleaner separation of logic into multiple files - Easier maintenance and scalability - Compatibility with standard Python package imports Includes: - src/constants.py, src/controls.py, src/game.py, src/modal.py, src/standard.py - src/assets/block.py, src/assets/bugs.py - __init__.py files to make src and assets proper packages
Ruff Lint check requirements
…ules This update adds a proper return type annotation (-> None), replaces the Any type with JsProxy for the event parameter, and prefixes it with _ to indicate it’s unused. A concise docstring was added to describe the function’s purpose, ensuring compliance with ANN201, D103, ANN001, and ARG001 linter rules.
Add modular PyScript setup with src package in virtual filesystem
…ls.py for separation of concerns
Shifted create_visual_grid into main, passive call through Utils. - Separating of concerns, for proper maintainability of code
…-screen Feature/save file and loading screen
build: set up Tailwind CSS v4 and migrate styles from vanilla CSS
… into feature/timer
…e in singleplayer/index.html
Updated Code Editor mode to inherit from BaseUIManager, BaseController, and BaseGameManager. Removed redundant logic by leveraging shared/, ensuring consistency with Singleplayer and Roguelike. Simplified mode workspace while keeping Code Editor–specific behavior isolated.
- Implemented undo/redo stacks in GameManager - Snapshots of the grid are stored on each block lock - Undo reverts to the previous grid state - Redo reapplies a reverted grid state - Redo stack is cleared after new moves for consistency
Feature/bgm support
feat:Add place sound for code editor
Final features
- Add video presentations for CodeRush and Roguelike. - Add preview screenshots - add goals.md and supporting images Update README.md Update README.md Update README.md
fisher60
left a comment
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.
README
The readme is very good. It is to-the-point, but also thoroughly detailed with sufficient run instructions as well as examples of the project. Clear examples are really great to see when it comes to open-source, it can really help a potential user decide if this is the right project for them. Though the emojis give heavy LLM vibes, they do a surprisingly good job at helping label sections, and the drop down buttons/sections are a very nice touch that keep the readme manageable and organized. I really appreciate the care that was taken to intuitively lay out the contents of the readme.
Commit Quality
Overall the commit quality is mixed. I see some really outstanding commits with excellent titles and descriptions. Though I see quite a few lackluster commits here as well. A lot of commits in this repo could use some better descriptions.
I like to see a quick summary of what has changed as well as any reasoning for the change that can add context during code review or for future developers on the codebase.
I would have also liked to see a standard format for commit messages. Many commits here are well formed with appropriate detail, but there is a lack of consistency. I appreciate seeing thoughtful commits with good structure, but I would recommend deciding on a preferred format for the team and sticking to it.
To summarize, the commit messages here are mostly what I would expect to see at a professional level, though the styling is a bit inconsistent.
Code Quality
Overall, the code quality is quite good. The codebase is well organized/structured and I did not spot anything alarming or super abnormal. It is clear that a lot of care was taken for styling and the logic is very sound.
Documentation
While I did see quite a few good and informative docstrings, a reoccurring issue I noticed was inappropriate documentation. The codebase is riddled with docstrings and comments that offer no utility or information to the reader. There are many places where the comments or docstrings are
completely unnecessary. I get the feeling that a lot of docstrings were added to comply with linting rules. As recommended in my review, I think this is an issue that can be solved by updating your linting config or putting in more thoughtful docstrings. When I am writing code comments or docstrings,
I like to think about what happens if I abandon the codebase and return to it much later. I ask myself some questions such as:
- What am I likely to forget the reasoning for (anything abnormal? Magic numbers? Something I spent a lot of time debugging and tweaked many times?)
- What logic takes a lot of time/effort to understand? (First I consider refactoring it to simplify it, if that can't be done I like to comment on it to make understanding it/reading it easier.)
- Is there anything unique I needed to learn/apply? I.e a new module or std lib functionality that is uncommon? Could be worth a brief not.
- Is there anything important my code doesn't do? Is there anything that isn't obvious that my code does do? (I.e does a function called "create_user_in_database" also create some other relationship? Does a specific function skip some safety check since it is expected to be performed before being called?)
Sometimes it can also be helpful to imagine you have someone brand new to programming who is going to be contributing to the project for the first time, is there anything you can document that could save them from needing to reach out to someone for help or otherwise spend a lot of time figuring out?
As for comments, there are way too many inline comments in this codebase. I believe that most of them can be fully removed as the code is self explanatory in these places. If you are writing a lot of inline comments, you should consider if they are necessary or if your code is unclear and needs to be refactored. There is really no reason to include loads of inline comments. If the functions you are calling have sufficient docs or the module being referenced has sufficient docs, you should expect that a developer can read those for themselves.
Structure
The organization of this codebase is very thoughtful and easy to follow. I really like that a consistent structure was decided on and that you stuck with it. It makes the code very easy to navigate and follow.
The code itself fit nicely into this structure. I did not find any modules that were overloaded with logic. The purpose of modules was quite clear and it made this codebase exceptionally to find my way through.
The one thing I would have liked to see is consolidating more shared logic to shared modules that can be reused. There were only a few spots that I saw this. While I am not a zealot for Don't Repeat Yourself, when you are copy-pasting identical functions to multiple places in the repo, that is a great chance to maintain some shared logic.
For a quick codejam, the impact will likely not be seen, but in a longer-living codebase condensing shared logic to dedicated modules can save a lot of pain while refactoring.
Overall, I do not have much to say about the organization, it is quite good and what I would expect at a professional level.
Formatting
Your formatting was great, using a linter/formatter is always a great idea and pretty much your entire project is perfectly formatted.
I did see a few odd spots where the typing was wrong, adding a static type checker is really the only step you could take to really improve this. I would always recommend using either pyright or mypy for the extra safety, sanity, and formatting.
And always running these tools as a build check required before merging PRs.
The Complete Picture
I get the feeling that there are professional devs involved in this repo. While I pointed out some issues in this summary and in the line-by-line review, largely what I saw in this project looks very good. I like to use the term "professional" or "enterprise" to
emphasize an expectation for code quality. I have spent enough time in industry to say that this project goes above and beyond what I commonly find in actual enterprise codebases. Your code structure, linting, and overall code quality is very thoughtful and it is clear
there is a lot of intention and intelligence in the decisions made for this project. I would like to see a bit more effort towards the readability in some places, sometimes the codebase sacrifices readability for what starts to look like "code golf", but overall I am impressed by this repo.
It makes me happy to see such a novel project backed by such a thoughtful codebase. While there is always room to improve, this project does a lot of things well.
| cd frontend | ||
| npm install | ||
| npm run build | ||
| python -m http.server |
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.
Nitpick/out of scope for a brief code jam, but be mindful of how this app is run. I see that multiplayer may be a future feature and this run method allows for path traversal, so could be risky to expose to the internet.
|
|
||
| from flask import Flask, render_template | ||
|
|
||
| template_dir = Path(__file__).resolve().parent.parent / "frontend" |
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.
This path is re-used in run.py, could be better off as a constant in something like settings.py, would maybe be nice to have it configurable with an env var as well.
|
|
||
| ## ⚙️ Setup Instructions | ||
|
|
||
| 1. Clone the repository: |
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.
While I appreciate how easy your app is to run, I really like adding docker as an option to full-stack projects. When there is a frontend and backend component, building and running can be nicely automated and simplified this way.
A really rough example of a Dockerfile (emphasis on rough) that could work for something like this is as follows:
FROM node:22-alpine as frontend
RUN mkdir /frontend-build
COPY ./frontend /frontend
WORKDIR /frontend
RUN npm install
RUN npm run build
FROM python:3.13-slim-bookworm
RUN mkdir /app
COPY --from=frontend /frontend /app
RUN python3 -m pip install poetry
RUN poetry config virtualenvs.create false
COPY . /app/
COPY backend /app/
COPY README.md /app/
WORKDIR /app
RUN python3 -m poetry install
CMD ["python3", "-m", "http.server"]Then run docker build -t grand-gardenias ., followed by docker run grand-gardenias -p 8000:8000
| app = Flask( | ||
| __name__, | ||
| template_folder=template_dir, | ||
| static_folder=static_dir, # serve static files from frontend/ |
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.
Some of these comments may be a bit overboard. If the code is self explanatory, I would avoid comments like this. My best advice here is to focus on the why for code comments. If no explanation for the "why" is needed/helpful, the comment can probably be discarded.
I.e static_folder=static_dir is very explicit in what it does, so the inline comment is not necessary. However, the next comment serve at root so /config.json works does provide some utility as it explains why you have written the code this way, not just what it does. That could provide important context to a future user. Although a good commit message could serve the same utility.
|
|
||
| from flask.cli import main as flask_main | ||
|
|
||
| DEFAULT_ARG_COUNT = 2 # Avoid magic number |
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.
This is a magic number. Good example of where a comment can help explain the why ;)
|
|
||
| def play_place_sound() -> None: | ||
| """Play the block place sound effect.""" | ||
| audio = Audio.new("/shared/audio/place.wav") |
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.
Bit of a nitpick, but it seems this should be defined once as a constant, that can be loaded when the application first loads, then played from within the function.
| class QuestionManager(metaclass=SingletonMeta): | ||
| """Manages question selection and updates the displayed question.""" | ||
|
|
||
| TOTAL_QUESTIONS: ClassVar[int] = 29 |
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.
Magic number could use some additional explanation.
| TOTAL_QUESTIONS: ClassVar[int] = 29 | ||
| # Questions excluded because they cause issues in this game mode | ||
| DEFAULT_EXCLUDED: ClassVar[set[int]] = {0, 6, 17, 18, 19, 20, 26, 29} |
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.
Nitpick: These do not need to be attributes in the class, these could be constants in the module. If you want to reference them from the class, maybe could be a property on the instance.
| def get_ques(id: int) -> dict: | ||
| """Get ques from json file.""" |
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.
The shorthand of question seems unnecessary here. Especially in the docstring.
|
|
||
|
|
||
| class GameManager(BaseGameManager): | ||
| # class GameManager(metaclass=SingletonMeta): |
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.
| # class GameManager(metaclass=SingletonMeta): |
No description provided.