Project for advanced software engineering which implements the game "Lights Out" in Python. In the game the player is supposed to click on the lights and switch all of them off by clicking on it. The difficulty is that each light is connected to its neighbors and switches them on/off as well. This results in an interesting riddle to solve random generated problems in a grid with the least amount of moves possible.
This game requires you to install and configure Python (at least version 3.9) and PIP. To start the game you can download the project with all files and execute the Powershell script which should setup the environment and start the game (see more under 10. Domain-specific language (DSL))
As an alternative you can start the project by executing the main.py file as entry point (after installing all dependencies).
The dependencies can be installed automatically by executing PyBuilders pyb.exe
. (see more under 6. Build Management)
The whole project is under version control using Git.
As UML diagrams the following were chosen:
- Class diagram → Go to PNG or PDF
- Package diagram → Go to PNG or PDF
- Use case diagram → Go to PNG or PDF
The tool draw.io (now diagrams.net) was used to create these. The class diagram represents the relationship between the classes in this project (as they are). For the package diagram and the use case diagram the project was pumped up artificially as if the funds of Edlich-Investment were used.
A Miro-Board was used for Event storming, creating the Core Domain Chart and indicating the relationship between the domains to apply Domain Driven Design in this project.
The metrices will be calculated by SonarCloud after every push to the main branch in GitHub. Therefore the metrices are always up-to date with the code from the main branch.
Sonarcloud scans all the code located in /src/main/python/
-
Don't repeat yourself (DRY)
→ Example 1: Use of constant to store repeating value
→ Example 2: Use of function to prevent repeating expression
-
Single level of abstraction
-
Usage of common design patterns →
→ Example 1: Model-View-Controller (MVC): Model, View, Controller
→ Example 2: Observer-Pattern: Observer, Observable
-
Separation of concerns
-
Small functions with descriptive names
-
Use of docstrings
→ And many more, look through the project
PyBuilder is used as the build automation/management tool for this project.
The project file structure was created according to PyBuilder's ecosystem.
With this tool the command pyb
can be executed on this project, which automatically installs all dependencies and runs the unit-tests.
To use the pyb
command in a shell, PyBuilder must be installed correctly into your Python installation.
To install PyBuilder simply run:
pip install pybuilder
Please keep in mind that if your Python installation is located in an admin-only-write directory such as the root directory, you need to run this command with admin privileges in order to use pyb
.
PIP will not tell you whether pyb
is working or not.
If you encounter problems using pyb
reinstall Pybuilder using admin privileges.
To analyze the behaviour of PyBuilder you can have a look in build.py.
The unit-tests are implemented using the unit testing framework of the Python Standard Library "unittest". The unit tests ensure that the logic of the program stays the same throughout further development.
- Click here to get to the directory where the unittests are located.
- 4 Unittests for the game logic: → click here
- 2 Unittests for the object containing the state of the play field → click here
For the UI itself there are no unit-tests implemented since most of the functions don't return a type that can be easily compared to a correct state. Nevertheless the UI is tested manually by hand to ensure that the components and the game interactions work as intended.
In this project GitHub Actions is used to establish a CI/CD pipeline. In the pipeline 2 jobs are being executed. The first job is the SonarCloud analysis (see 4. Metrices) which updates the metrics for the source code in the main branch. The second job calls PyBuilder which installs the dependencies and runs the unit-tests. After completion of the pipeline SonarCloud and PyBuilder report if the check succeeded or failed which will be shown next to the commit in the history.
- Go to the pipeline: build.yml
For this project Visual Studio Code was used as primary IDE.
Favourite key shortcuts:
- Show/Hide Primary Side Bar (e. g. Project explorer):
Ctrl
+B
- Show/Hide Lower Panel (e. g. Terminal):
Ctrl
+J
- Refactor code:
Ctrl
+Shift
+R
- Debug project:
F5
- Open command pallete:
Ctrl
+Shift
+P
- Rename variable/function/etc.:
F2
For domain-specific language there is a script implemented for Windows PowerShell which setups this project and starts the game. To setup it will be checked whether the Python version is at least 3.9 and PIP is available. Therefore to run the script Python 3.9 must be installed and the path variables for Python and PIP must be configured correctly under Microsoft Windows so the script can call Python and PIP from the terminal. After checking for the entry point of this project, PyBuilder will be installed through PIP and the build process will be started which then installs all necessary dependencies for the game and executes the unit tests as configured in setup.py and build.py. At the end the main.py file will be called which starts the game.
To start the script you can right-click on the file setup_and_start_game.ps1
in the project path and choose the option Run with PowerShell
in the context menu.
Unfortunately due to some edge cases with the Python installation the script must run with admin privileges to bypass the issue. This might lead to an UnauthorizedAccess
error. To resolve this follow point 1 under known issues below.
There are certain issues that can be encountered when executing the script.
-
Since the script requires admin privileges the default Windows Execution Policy will block the PS-script. To solve this issue you must set the Execution Policy to Unrestricted using this command in Powershell:
Set-ExecutionPolicy -ExecutionPolicy Unrestricted
To reset the ExecutionPolicy to default after you are finished you can use:
Set-ExecutionPolicy -ExecutionPolicy Default
-
If you get the error message that the term
pyb
is not recognized it is most likely because of a previous corrupt installation of PyBuilder. To resolve this issue a reinstallation of PyBuilder might do the trick. To be on the safe side you can run this command in a terminal with admin privileges:pip install --force-reinstall pybuilder
The aspects of Functional Programming are covered in this project. Click the aspects to see to the examples.
-
The data for this project is stored in primitive data types such as boolean, integer, etc. and are therefore final.
-
(Mostly) Side effect free functions
Most of the functions have no side effect and only fulfill one specific task which is visible in their name.
-
Use of higher-order functions / Functions as parameters and return values
Instead of for-loops there are many examples where the map-function is used in combination with an anonymous function as a parameter.
-
Use closures / anonymous functions
Anonymous functions / Lambdas are used mostly in map/filter-functions to replace for-loops.