Code Monkey home page Code Monkey logo

adcap-clone's Introduction

Description

A browser based adventure capitalist clone with basic functionality. Features:

  • Purchasing of buildings
  • Purchasing of managers
  • Ability to "work" a building to earn money after the "work" is completed
  • When a manager is purchased the associated building should be worked automatically
  • When the user is offline and reload the applicaiton, any managers assigned should have earned income while the user was away.
  • Full stack application with backend validation and syncing from the backend
  • User can reset their application to start over

Deployed demo can be found here

Architecture

Straight forward frontend react app + nodejs backend + postgres. Backend/frontend communication is a via simple API. Core architecture decision being the shared reducers that are used to optimistically update the UI state and also update stored state while also validating. If validation fails then state is reverted to last known good.

User state definition

interface IState {
  buildings: { [key: number]: { tier: number; lastCompletedAt: number } };
  managers: number[];
  money: number;
}

interface Action {
  type: string;
  payload: any;
}

Backend

Backend has two core functions, get state and save state.

  • GET /state/:deviceId will upsert the user based on their device_id (generated and saved on the frontend) and return the current state. In addition when the app state is loaded, we fast forward any work done by "managers" before sending the state to the client. The income earned from fast-forwarding is additionalIncome.

Response {state: IState, additionalIncome: number}

  • POST /state/:deviceId applies state updates in order. If an update occurs applying any of the state update, an error and the last-known-good state are returned

Request {actions: Action[]}

Response {state: IState, error?: string }

Knex is used for querying as well as migrations. Schema:

(users)
  id: integer primary key
  device_id: varchar(255)
  state: text

Frontend

  • On initial load a deviceId is generated and stored in local browser storage, user can reset this which will generate a new deviceId which will reset their application
  • Uses a simple state object injected via context and a redux-like dispatch pattern to trigger reducers with payloads
  • the useGameState hook does a lot the heavy lifting with respect to backend communication and initializing the application

    This hook buffers state updates and syncs to backend every 500 milliseconds

Tradeoffs

  • No user authentication. We simply generate a device_id on frontend load and save that, user authentication/management seemed out of scope.
  • 1 session per device right now, because of the way state is fast forwarded, running multiple sessions on the same device will mess this up. This is currently not enforced but revision ID's would allow us to enforce this.
  • Not much work was put into ui design, I'm certainly not a designer.

Possible Improvements

  • Real world I would normally use styled-components organized with some sanity and some shared css. Currently just a big css file.
  • Replace the symlink module sharing with lerna or something so we can treat them as a shared node module.
  • I didn't bother adding indexes to the db but for a start you definetly want one a unique one on users.device_id since its our lookup key most of the time.
  • I would normally dockerize the whole app so that to get started development you just run docker-compose up. I didn't bother here.
  • I haven't bothered with tests.. I normally believe in pretty aggressive testing practices especially in places like the core reducers and lib functions.

Development

  • Start the database docker-compose up -d
  • Run migrations from backend/ yarn run migrate
  • Start the backend (from backend/ again) yarn run dev
  • From another terminal start the frontend in frontend/ folder yarn run start

adcap-clone's People

Contributors

jakedavies avatar

Watchers

James Cloos avatar  avatar  avatar

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.