Inkposter
October 16, 2024 ยท View on GitHub
Inkposter
Inkposter is a browser-based multiplayer party game for 3-9 players based on skribbl.io, Gartic Phone and Fake Artist goes to New York made for course DH2643 @ KTH.
Table of Contents
๐ Description
How to play
The game requires one host device where everything shared is displayed and 3-9 player devices where you see your personal prompts and drawings.
At the start of the game everyone receives a prompt that relates to a theme, except 1 player who is an Inkposter. No one knows what the theme is and no one knows who the imposter is. The Inkposter needs to observe the other drawings to blend in with the rest. The innocent players need to also pay attention to who might be late to draw without revealing too much information about the theme. Everyone draws on their personal devices and can see everyone else's drawings on the host device's screen.
When the timer runs out voting begins. The players vote what they suspect the theme is and who they think the Inkposter is. If the majority of players vote for the Inkposter then they're caught!
It is recommended to play the game using your phone and host the game on a big screen (e.g. TV, computer screen, livestream).
Demo
The layout is designed in Figma following: https://www.figma.com/design/V4OLczauxQRw13nV0fefb7/Inkposter-Design?node-id=2407-292&node-type=frame&t=S5xK8qXW5BX97cNm-0 (Also see: Architecture).
A demo is deployed on Heroku: https://inkposter-917d97c7bb64.herokuapp.com.
๐ ๏ธ Setup
Prerequisites:
- You will need env variables
MongoDB_URI,OpenAPI_KEY,GITHUB_CLIENT_IDandGITHUB_CLIENT_SECRETset.
Built with
- React v.18.3.1
- Node.js
- Express
- MongoDB
- Socket.io
- OAuth 2.0 on GitHub
- TailwindCSS
- TypeScript
- Jest + React Testing Library
- Docker
Favicon created by smalllikeart - Flaticon and react-sketch-canvas package by Vinoth Pandian.
Getting started
To start the REST API server and the client application:
Docker-compose (recommended during development)
The docker image for Inkposter is deployed on: https://hub.docker.com/repository/docker/ziyi01/inkposter/.
- Build the image using
docker-compose.ymlfrom root:
$ docker-compose build
- Run the development environment/docker container on
localhost:3000:
$ docker-compose up -d
Use docker-compose down -v to close the container process.
npm CLI
- Install npm dependencies with:
$ npm run dev-build
- Start the server on
localhost:3000with:
$ npm start
To run either the frontend or the backend application separately, enter the app or server folder:
- Install npm dependencies with:
$ npm install
- For the frontend application
apprun:
$ npm run build
- Run the application with:
$ npm start
๐งช Workflows
| File | Workflow | Description | On |
|---|---|---|---|
node.js.yml | Node.js CI | Build and run tests | Pull and Push to main-branch |
test.yml | Coverage | Runs tests and create coverage report | Pull main-branch |
docker.yml | Docker CI | Deploys the docker image | Push to main-branch |
main.yml | Deploy | Deploys the application to Heroku | Pull request main-branch |
Tests
Test coverage is reported when creating a pull-request into the main-branch. The tests uses Jest for unit testing and setup using babel.config.js and jest.config.js.
Unit tests are separated into the folders ./app/__tests__ for UI tests and ./server/__test__ for server tests:
| File | Test | Type |
|---|---|---|
App.test.tsx | Login page has login button | UI test |
App.test.tsx | Homepage has join game button | UI test |
App.test.tsx | Profile has log out button | UI test |
db.test.js | Create and delete user | Database test |
db.test.js | Retrieve user stats | Database test |
db.test.js | Update username and retrieve user | Database test |
route.test.js | /api/user/0 return test user | REST API test |
route.test.js | /api/user/0/userStats return stats | REST API test |
route.test.js | /api/user/10000 return 404 | REST API test |
route.test.js | /api/openai/username should return 200 | REST API test |
route.test.js | /api/openai/sessionPrompts should return 200 | REST API test |
๐ Architecture
Architecture and file structure in the project.
API endpoints
All API-endpoints are accessed at https://inkposter-917d97c7bb64.herokuapp.com//api/{route}.
| Method | URL | Description |
|---|---|---|
POST | /user | Create and persist user with unique userID |
GET | /user/:userID | Get user information {name, avatar, previous themes} |
GET | /user/:userID/userStats | Get stats from user's previous games |
PATCH | /user/:userID/username | Update username |
PATCH | /user/:userID/avatar | Update avatar |
PATCH | /user/:userID/previousTheme | Add current theme to users previous themes |
PATCH | /user/:userID/sessionResults | Increment relevant wins/losses and add drawing to user's gallery |
DELETE | /user/:userID/delete | Delete user |
GET | /openai/username | Return a unique username generated by OpenAI |
GET | /openai/sessionPrompts | Return json object with theme and prompts for both innocents and inkposter |
GET | /github/login | Login route |
Socket communication
Socket.io is used for real-time communication with the server and clients during the game. The clients are divided into host (the client whose display is used to show all drawings and triggers start of the game) and players (usually on a phone, where they draw and can see their role and prompt).
Below shows the events emitted and what each role does in the communication chain (not including error handlers):
Front-end
The front-end application uses a MVP-architecture. The code is divided into folders components (for repeated components and cripts), presenters and views. userModel.tsx is the model for the application and the app is mounted using App.tsx and index.tsx.
โโโ src/
โโโ components/
โ โโโ button.tsx
โ โโโ canvas.tsx
โ โโโ githubCallback.tsx
โ โโโ layout.tsx
โ โโโ navbar.tsx
โ โโโ playerInterface.ts
โ โโโ popup.tsx
โ โโโ route-component.tsx
โ โโโ server-requests.ts
โ โโโ socket-client.tsx
โ โโโ timer.tsx
โโโ presenters/
โ โโโ homepage-presenter.tsx
โ โโโ host-end-presenter.tsx
โ โโโ host-game-presenter.tsx
โ โโโ host-voting-presenter.tsx
โ โโโ host-waiting-presenter.tsx
โ โโโ login-presenter.tsx
โ โโโ player-end-presenter.tsx
โ โโโ player-game-presenter.tsx
โ โโโ player-voting-presenter.tsx
โ โโโ player-waiting-presenter.tsx
โ โโโ profile-presenter.tsx
โโโ views/
โ โโโ homepage.tsx
โ โโโ host-game.tsx
โ โโโ host-session-end.tsx
โ โโโ host-voting.tsx
โ โโโ host-waiting.tsx
โ โโโ loading.tsx
โ โโโ login-page.tsx
โ โโโ mock-login.tsx
โ โโโ player-game.tsx
โ โโโ player-session-end.tsx
โ โโโ player-voting.tsx
โ โโโ player-waiting.tsx
โ โโโ profile.tsx
โโโ App.css
โโโ App.tsx
โโโ global.css
โโโ index.css
โโโ index.tsx
โโโ userModel.tsx
Back-end
The back-end is quite short, routes/api.js contain the REST endpoints of the app. bin/www initialises the server and socket.io. db.js, openai.js and socket.js implement MongoDB, OpenAI and socket.io respectively.
โโโ server/
โโโ bin/
โ โโโ www
โโโ routes/
โ โโโ api.js
โโโ app.js
โโโ db.js
โโโ openai.js
โโโ socket.js