Git Product home page Git Product logo

ffp's Introduction

Minesweepskell - a fun(ctional) Web Minesweeper written in Haskell

Haskell CI

Advanced Functional Programming - Group project (2020)

Description

Minesweepskell is a web implementation of the widely known video game Minesweeper fully written in the functional programming language Haskell.

Features

  • Minesweeper Web App with three predefined difficulties as well as customisable games
  • Slim & blazing fast UI powered by server side events
  • Join other players on their game either to view them playing or to play together
  • Pause games & continue later
  • History of all finished games to revisit your best & worst performances

landingpage game

Architecture

Web application with the Yesod framework

  • REST Backend
  • Frontend fully developped in Yesods shakespearean templating system
  • Server-side events in order to provide live UI rerendering and updates for a flawless User Interface, which even has the possibility to play/view one game on multiple Bowsers/Machines simultaneously

Global mutable in-memory state with TVars

  • Global state of all ongoing games realized with TVars, which provide mutability as well as atomic writing operations
  • The state only contains all ongoing games, paused and finished (lost/won) games are moved from the in-memory state to the database, if a paused game is continued it will be loaded back into the in-memory state

Database with Persistent & MongoDB

  • As just mentioned Minesweepskell stores non-ongoing games in a database this is realized by using the Persistent library to connect a MongoDB

Elegant data accessing/manipulation with Lenses

  • In order to manipulate and query data types more elegantly lenses are used for almost all operations on data types
  • Lenses for matrices are provided by the matrix-lens package and provide elegant manipulation of cells on the game board

Utilisation of Monads

  • Monads are widely used throughout the project, especially the IO monad for things like state manipulation, as well as Yesods Handler Monad for the REST API, own Monads are not defined
  • Problem: Initially we wanted to realize the global mutable state with the State monad, but we could not get it to work in combination with Yesods handler monad. Due to this we switched to TVars for the global in-memory state, which proved to be a better choice, since it even provides atomic writing operations and was astonishingly smooth to implement for our use cases.

Installation

Run in the project folder stack build.

Requirements

$ stack --version
Version 2.3.3 x86_64

$ yesod version
yesod-bin version: 1.6.0.6

Install Haskell and Yesod

  1. Install haskell-stack and yesod
# - if it fails run `xcode-select --install before`
brew install haskell-stack
stack install yesod-bin --install-ghc
  1. Add yesod installation path to your shell
# ~/.zshrc
export PATH=$HOME/.local/bin:$PATH

If you have trouble, refer to the Yesod Quickstart guide for additional detail.

Install MongoDB

  1. Install MongoDB
brew tap mongodb/brew
brew install [email protected]
  1. Run MongoDB
brew services start [email protected]
brew services stop [email protected]
  1. Verify that it is running ps aux | grep -v grep | grep mongod, logs can be found here /usr/local/var/log/mongodb/mongo.log. and settings here /usr/local/etc/mongod.conf

For more information take a look at https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/

  1. Use MongoDB Compass as GUI

Usage

stack build && stack exec -- yesod devel to run the project locally.

Development

  • Build libraries: stack build
  • Start a development server with stack exec -- yesod devel, it watches for changes and recompiles the project automatically.
  • Go to http://localhost:3000 to see landing page
  • Run stack clean --full && stack build to clean the project and to rebuild it.
Adjust GHC prompt
  • add the following to your ~/.ghc/ghci.conf
:set prompt      λ:
:set prompt-cont λ|

https://stackoverflow.com/a/47694134

Tests

stack test --flag minesweepskell:library-only --flag minesweepskell:dev

(Because yesod devel passes the library-only and dev flags, matching those flags means you don't need to recompile between tests and development, and it disables optimization to speed up your test compile times).

Dependencies (excerpt)

yesod
mongodb
persistent
lens
matrix-lens
...

For more details take a look at the package.yaml.

Code formatting

Along with the IntelliJ plugin for Haskell Ormolu is used as automatic code formatter.

Contributors

  • Andreas Ellwanger
  • Timo Erdelt
  • Andreas Griesbeck

Individual contributions

Due to the small group size of 3 it is impossible for us to properly distinguish what of our project has been done by whom. We all worked on all parts of our application, especially since we mostly did “pair-programming” (with two or often all three of us working together). So all of us were equally involved in all parts of our application. We would be happy to answer questions about our development process, as well as our individual/collective contributions at the examination.

ffp's People

Contributors

griase94 avatar ndrsllwngr avatar tmrdlt avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

ffp's Issues

Switch db to mongo

TODO
  • Apply changes of stack new minesweepskell yesodweb/mongo to our current project
  • Update github workflow
  • rm postgres from package.yml

fyi

  • run stack build after checking out these changes
INFO

Diff between mongo and postgres

$ diff -qr ffp test/minesweepskell --exclude=".stack-work" --exclude=".*" | sort
TODO
Files ffp/src/Application.hs and test/minesweepskell/src/Application.hs differ
Files ffp/test/TestImport.hs and test/minesweepskell/test/TestImport.hs differ
DONE
Files ffp/templates/default-layout.hamlet and test/minesweepskell/templates/default-layout.hamlet differ
Files ffp/templates/homepage.hamlet and test/minesweepskell/templates/homepage.hamlet differ
Files ffp/test/Handler/CommentSpec.hs and test/minesweepskell/test/Handler/CommentSpec.hs differ
Files ffp/src/Settings.hs and test/minesweepskell/src/Settings.hs differ
Files ffp/src/Model.hs and test/minesweepskell/src/Model.hs differ
Files ffp/src/Handler/Home.hs and test/minesweepskell/src/Handler/Home.hs differ
Files ffp/src/Handler/Comment.hs and test/minesweepskell/src/Handler/Comment.hs differ
Files ffp/src/Foundation.hs and test/minesweepskell/src/Foundation.hs differ

Files ffp/stack.yaml and test/minesweepskell/stack.yaml differ
Files ffp/stack.yaml.lock and test/minesweepskell/stack.yaml.lock differ
Files ffp/minesweepskell.cabal and test/minesweepskell/minesweepskell.cabal differ
Files ffp/package.yaml and test/minesweepskell/package.yaml differ
Files ffp/config/settings.yml and test/minesweepskell/config/settings.yml differ
Files ffp/config/test-settings.yml and test/minesweepskell/config/test-settings.yml differ

Only in ffp/config: client_session_key.aes

Only in ffp/static: tmp

Only in ffp: minesweepskell.iml
Only in ffp: yesod-devel

Files ffp/README.md and test/minesweepskell/README.md differ
Only in ffp: README-yesodweb-postgres.md

Only in ffp/config: models.persistentmodels
Only in ffp/config: routes.yesodroutes
Only in test/minesweepskell/config: models
Only in test/minesweepskell/config: routes

Notes / Resources

Further ToDos

SPRINT GOAL ♦️
  • Apply lenses to Data.matrix #28
  • Use actual randomSeed (either via user input or generated) #29
  • Add ServerSideEvents [Tfoo, Chan] to update UI instantly 🗼 #31
  • Human Readable unique GameID generieren (like HarmfulExpectationsCeaseParticularly) @timunkulus
  • Generate games of predefined sizes / difficulty ⚡️
  • Rework user interface (minimal and clean design language, remove boilerplate) #30 @ndrsllwngr @timunkulus
    • Render digits using Attributes to remove flickering
    • Add game instructions (controls)
    • Go Back & Pause Button is just one
    • Completed game history in colors
  • BUG: It should be possible to put only as many flags as totally available @griase94
  • BUG: Show elapsed time of finished games @timunkulus
  • BUG: Pause a game that has no move yet will cause timeElapsed to be already counted @timunkulus
  • On reset finished game: leave game in DB and create new gameID @griase94
  • Update README.md (incl. usage, topics and short description) and align with lecture topics 🔺 #17 (comment)
  • Refactor project, cleanup code, align routes, give variables suitable names [86bae6f]
  • Format files with linter (e.g. stylish-haskell -r -i src/*), be careful that {-# LANGUAGE are preserved
  • Test project
    • game logic
    • moves
    • interactions & routing
    • warnings
BACKEND
  • Don't allow flagging of already revealed cells
  • Error Handling in Requests und Logik (z.b. outOfBound) ❓
FRONTEND
  • Landing page: Show total time of each game which is in final state (lost/won)
OPTIONAL
BUGS
  • Performance Issues ❓
NOT DOING
  • host project on heroku (https://github.com/mfine/heroku-buildpack-stack)
  • UI - implement right-click instead of alt+left-click to flag a cell
  • UI - add pressed state to unrevealed cell & face status
  • Leaderboard (sorted by time, grouped by size+difficulty) would be possible, if we would allow players to enter username (similar to retro game machines)
  • Add unit-tests
  • Error handling on route responses (e.g. show not found page)
  • Make use of advanced monads
  • Game page: Show move history on /game/#id page (🤔 not sure if useful at all. any information gain?)

DONE
  • View updated sich nach Move 32febbe
  • Bomben durchstreichen wenn angeklickt und danach Spiel abschließen d0b3c7d
  • Reveal All wenn alle Bomben geflaggt wurden d0b3c7d
  • Spiel vorzeitig abschließbar machen können (Related #15)
  • Zeit reinbringen und anzeigen
  • Reset Route and action in front end
  • Add reveal all button (makeMove)
  • Stop timer if final state of game 10f2a25
  • add face button in the middle with different emotions
  • Pause Game Funktion (führt zu Startseite zurück)
  • Reveal all button
  • Anzahl an übrigen Flags anzeigen bc8684e
  • Spiel in Datenbank als nur ein Eintrag abspeichern ed7b3d2
  • Game Logik anpassen: Spiel ist erst gewonnen, wenn alle Flags verteilt wurden!
  • localhost is hardcoded at the moment, better solution? b2ac90b
  • Landing page: List all paused/ongoing games which are in the DB 2ee7cc3
  • Lift state and only save paused or finished games in db #27
  • Make use of lenses #25
  • Make use of TVars #27
  • Warnings Fixen [cb3c361, #26 ]

REQUIREMENTS (Uni2Work)
  1. Webapplikation mit yesod
  2. Monaden

Fortgeschrittenere Themen, welche sich zu Monaden anrechnen lassen sind z.B. Monad-Transformer, Lifting, fortgeschrittene Verwendungen von Zustandsmonaden, etc.
Beachten Sie bitte, dass zu einer zufriedenstellenden Anrechnung des Themas Monaden mehr als einfacher monadischer Code (z.B. nicht nur do-Notation) vorhanden sein muss.

  1. Datenbankanbindung (Persistent)

zusätzlich eine Datenbankanbindung implementieren (z.B. mit Persistent), beispielsweise um Spielstände persistent zu speichern, um zu einem späteren Zeitpunkt mit dem Spiel fortfahren zu können.

  1. Tests (?)
  2. AI/Automated Problem Solving

Das Thema KI / Automated Problem Solving ist des Weiteren nicht direkt ein Thema der funktionalen Programmierung.

UPDATED REQUIREMENTS
  1. TVars (nebenläufigkeit)

TVars decken ja eigentlich sogar auch Nebenläufiges Programmieren

  1. Lenses

Sie könnten noch ein paar Lenses für irgendwelche Datentypen (die sie ja wahrscheinlich sowieso haben) definieren und deren Verwendung demonstrieren.

  1. Unlösbare Probleme (State monade)

Die unlösbaren Probleme sind sicherlich auch ein guter Punkt, den Sie in der Abgabe ja kurz dokumentieren und begründen könnten (was geht da, warum nicht).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.