Giter Club home page Giter Club logo

hpi-sam / digital-fuesim-manv Goto Github PK

View Code? Open in Web Editor NEW
16.0 3.0 8.0 13.57 MB

A German simulation system for training emergency medical services leadership personnel on how to manage Mass Casualty Incidents.

Home Page: https://fuesim-manv.de/

License: GNU Affero General Public License v3.0

JavaScript 1.08% TypeScript 86.56% HTML 11.88% SCSS 0.09% Shell 0.20% Dockerfile 0.19% Batchfile 0.01%
mci angular emergency-medical-services germany immerjs nodejs openlayers typescript simulation training

digital-fuesim-manv's Introduction

Digitale FüSim MANV

If you're interested in the most recent stable release, please check out the main branch.

This is the codebase for a digital implementation of the "FüSim MANV" (Führungssimulation Massenanfall von Verletzen), a German simulation system for training emergency medical services leadership personnel on how to manage Mass Casualty Incidents.

You can try it out at https://fuesim-manv.de/.

image A screenshot of a part of an MCI exercise with initially ca. 50 patients at the Brandenburg Gate.

The concept is as follows:

  • A trainer creates an exercise, which consists of patients, vehicles, viewports, transferPoints and other objects placed on a map.
  • Participants can then join the exercise.
  • The trainer can restrict the participants to a specific viewport. The participant cannot move out of this area.
  • Vehicles (containing material, personnel and (sometimes) patients) can be transferred to other areas via transferPoints.
  • After the exercise is started, patients that are not adequately treated by personnel and material can deteriorate and die. The goal of the participants is to prevent the patients from dying and transport them to the hospitals. To do this effectively they have to communicate with each other (via real radio devices, or remote via third-party services) and make the right decisions.
  • Afterward, the exercise can be evaluated via statistics and a "time-travel" feature.

This simulation has been designed in cooperation with and with support from the Federal Academy for Civil Protection and Civil Defence of the Federal Office of Civil Protection and Disaster Assistance Germany, who are the original copyright holders of the analog "FüSim MANV" simulation system, and the Malteser Hilfsdienst e.V. Berlin as well as the Johanniter Akademie NRW, Campus Münster der Johanniter-Unfall-Hilfe e.V.

The simulation is implemented as a web application with an Angular frontend and NodeJS backend.

This project is currently developed as a bachelor project at the HPI. You can find the official project website here.

Links for collaborators

  • Internal test scenarios
    • Used only for private testing
  • Public test scenarios
    • Used for test scenarios in pipelines, Can also be used for private testing
    • For usage see the README.md in that repo
    • This repo is also a submodule of this repo. Use --recurse-submodules when cloning the repo or run git submodule update --init --recursive if you have cloned the repo already to get its contents.

Installation

  1. Install NodeJs (at least version 18.x) (if you need different node versions on your machine we recommend nvm or nvm for windows)
  2. npm should already come with NodeJs - if not install it
  3. Clone the repo by running git clone https://github.com/hpi-sam/digital-fuesim-manv. To be able to run migration tests, you also have to clone the submodules: use git clone --recurse-submodules https://github.com/hpi-sam/digital-fuesim-manv or run git submodule update --init --recursive if you have cloned the repo already.
  4. Run npm run setup from the root folder
  5. Copy the .env.example file to ./.env and adjust the settings as you need them. Note that some of the variables are explained under the next point.
  6. Choose whether you want to use a database: You can (optionally) use a database for the persistence of exercise data. Look at the relevant section in the backend README for further information. Note that to not use the database you have to edit an environment variable, see the relevant section.
  7. (Optional) We have a list of recommended vscode extensions. We strongly recommend you to use them if you are developing. You can see them via the @recommended filter in the extensions panel.
  8. (Optional) We have prepared default settings, tasks and debug configurations for VS Code. You can find them in .vscode/*.example. Crete a copy of those files removing the .example and adjust them to your needs. The files without .example-Extensions are untracked so your adjustments won't be committed automatically.

Starting for development

Option 1

If you are using vscode, you can run the task Start all to start everything in one go. Note that this tries to start the database using docker compose. In case this fails please start the database in another way (see this section in the backend README). If you're not using a database anyway, you could use the task Start all but database instead.

Option 2

  1. Open a terminal in /shared and run npm run watch
  2. Open another terminal in /frontend and run npm run start
  3. Open another terminal in /backend and run npm run start
  4. Consider the database -- see point 7 of the installation.

Starting for deployment (using docker)

You need to have docker installed.

With docker compose (recommended)

  1. docker compose needs to be installed. Note that, depending on your setup, you may use docker-compose instead of docker compose. In this case, just replace the space in the commands with a dash (-). For more information, see the relevant section of the documentation.
  2. Run docker compose up -d in the root directory. This also starts the database. If you don't want to start the database run docker compose up -d digital-fuesim-manv instead.

Without docker compose

  1. Execute docker run -p -d 80:80 digitalfuesimmanv/dfm.

The server will start listening using nginx on port 80 for all services (frontend, API, WebSockets).

Note the database requirements depicted in the installation section.

Building the container from scratch

Option 1

  1. Uncomment the build section of the docker compose file.
  2. Run docker compose build

Option 2

  1. Run docker build -f docker/Dockerfile -t digital-fuesim-manv .

Docker volumes / persistent data

Docker ENVs

  • All available Docker ENVs are listed with their default values in .env.example file. Copy this file and name it .env (under Linux, this would be e.g. cp .env.example .env)

Before you commit

  • We are using prettier as our code formatter. Run it via npm run prettier or npm run prettier:windows in the root to format all files and make the CI happy. Please use the vscode extension.
  • We are using eslint as our linter. Run it via npm run lint:fix in the root to lint (and auto fix if possible) all files. Please use the vscode extension.

Debugging

There are already the following debug configurations for vscode saved:

  • Launch Frontend [Chrome]
  • Launch Frontend [Firefox] (You have to install an extra extension)
  • Debug Jest Tests

In addition, you can make use of the following browser extensions:

Testing

Migration tests

Whenever adding a new action or new state altering ui components (things that a user can use to alter the state in new ways) one should add exports of exercises in which the new features where tested to the Public test scenarios

The test scenarios are stored in a submodule. Use --recurse-submodules when cloning the repo or run git submodule update --init --recursive if you have cloned the repo already.

If you wish to run the migration tests use npm run test:migration

Unit tests

We are using Jest for our unit tests.

You can run it during the development

  • from the terminal via npm run test:watch in the root, /shared, /backend or /frontend folder
  • or via the recommended vscode extension. (Note: this option is currently broken)

End to end tests

We are using cypress to run the end-to-end tests. You can find the code under /frontend/cypress in the repository.

Running the tests

To run the tests locally, it is recommended to use the vscode task Start all & cypress. Alternatively, you can start the frontend and backend manually and then run npm run cy:open in /frontend.

If you only want to check whether the tests pass, you can run npm run cy:run in /frontend instead.

Benchmarking

You can run the benchmarks via npm run benchmark in the root folder. Look at the benchmark readme for more information.

Styleguide

  • names are never unique, ids are
  • Use StrictObject instead of Object wherever possible
  • A leading underscore should only be used
    • for private properties that may be used with getters/setters
    • to resolve certain naming conflicts (e.g. .some(_item => ...))
  • dependencies should be used for packages that must be installed when running the app (e.g. express), whereas devDependencies should be used for packages only required for developing, debugging, building, or testing (e.g. jest), which includes all @types packages. We try to follow this route even for the frontend and the backend, although it is not important there. See also this answer on StackOverflow for more information about the differences.
  • Use JSDoc features for further documentation because editors like VSCode can display them better.
    • Be aware that JSDoc comments must always go above the Decorator of the class/component/function/variable etc.
    /**
     * Here is a description of the class/function/variable/etc.
     *
     * @param myParam a description of the parameter
     * @returns a nice variable that is bigger than {@link myVariable}
     * @throws myError when something goes wrong
     */
  • You should use the keyword TODO to mark things that need to be done later. Whether an issue should be created is an individual decision.
    • You are encouraged to add expiration conditions to your TODOs. Eslint will complain as soon as the condition is met. See here for more information.
    // TODO [engine:node@>=8]: We can use async/await now.
    // TODO [typescript@>=4.9]: Use satisfies https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html#the-satisfies-operator

Releases

Versions

Version numbers follow the pattern ${major}.${minor}.${patch}. major, minor and patch are decimal numbers without leading zeroes, similar to SemVer. But since we do not have a public API, we do not adhere to SemVer.
The major version is updated for breaking changes, i.e. old state exports of configured exercises that have never been started, cannot be imported.
The minor version is updated with every release on main. State exports of configured exercises from older minor versions that have never been started must successfully import and started exercises should be importable and behave consistently with older versions, although this is not strictly required.
The patch versions is incremented if and only if critical issues on main are being fixed during a milestone.

Every time a part of the version number is updated, all numbers to the right are reset to zero. For each new release, pull requests both to main and dev are created from the same release/ branch. For scheduled releases, such PRs are created by the Create Release PR workflow.

Workflows

With every significant PR into dev, the change must be briefly described in CHANGELOG.md. Pay attention to Keep a Changelog.

The Create Release PR workflow accepts a new version number, updates the version in all relevant source files and moves the Unreleased section in CHANGELOG.md to a release heading, creating a new Unreleased section. It then prepares two draft PRs, one into dev and one into main with these changes. They have to be marked as ready to run the pipeline and need approval. Merge them without rebase (use merge commit option).

Upon pushing to main or dev, GitHub Actions will build and push docker containers to Docker Hub tagged latest and dev. latest is additionally tagged with the current version number on main and a GitHub release is created.

Architecture

This repository is a monorepo that consists of the following packages:

  • frontend the browser-based client application (Angular)
  • backend the server-side application (NodeJs)
  • benchmark benchmarks and tests some parts of the application
  • shared the shared code that is used by the frontend, backend and the benchmark package

Each package has its own README.md file with additional documentation. Please check them out before you start working on the project.

One server can host multiple exercises. Multiple clients can join an exercise. A client can only join one exercise at a time.

State management and synchronization

This is a real-time application.

Each client is connected to the server via a WebSocket connection. This means you can send and listen for events over a two-way communication channel. Via socket.io it is also possible to make use of a more classic request-response API via acknowledgments.

State, actions and reducers

We borrow these core concepts from Redux.

What is an immutable JSON object?

A JSON object is an object whose properties are only the primitives string, number, boolean or null or another JSON object or an array of any of these (only state - no functions). Any object reference can't occur more than once anywhere in a JSON object (including nested objects). This means especially that no circular references are possible.

An immutable object is an object whose state cannot be modified after it is created. In the code immutability is conveyed via typescripts readonly and the helper type Immutable<T>.

State

A state is an immutable JSON object. Each client as well as the server has a global state for an exercise. The single point of truth for all states of an exercise is the server. All these states should be synchronized.

You can find the exercise state here.

Action

An action is an immutable JSON object that describes what should change in a state. The changes described by each action are atomic - this means either all or none of the changes described by an action are applied.

Actions cannot be applied in parallel. The order of actions is important.

It is a bad practice to encode part of the state in the action (or values derived/calculated from it). Instead, you should only read the state in the accompanying reducer.

Reducer

A reducer is a pure function (no side effects!) that takes a state and an action of a specific type and returns a new state where the changes described in the action are applied. A state can only be modified by a reducer.

To be able to apply certain optimizations, it is advisable (but not necessary or guaranteed) that the reducer only changes the references of properties that have been changed.

You can find all exercise actions and reducers here. Please orient yourself on the already implemented actions, and don't forget to register them in shared/src/store/action-reducers/action-reducers.ts

Immutability

It isn't necessary to copy the whole immutable object by value if it should be updated. Instead, only the objects that were modified should be shallow copied recursively. Immer provides a simple way to do this.

Because the state is immutable and reducers (should) only update the properties that have changed, you can short circuit in comparisons between immutable objects, if the references of objects in a property are equal. Therefore it is very performant to compare two states in the same context.

To save a state it is enough to save its reference. Therefore it is very performant as well. If the state would have to be changed, a new reference is created as the state is immutable.

Large values (WIP)

Large values (images, large text, binary, etc.) are not directly stored in the state. Instead, the store only contains UUIDs that identify the blob. The blob can be retrieved via a separate (yet to be implemented) REST API.

The blob that belongs to a UUID cannot be changed or deleted while the state is still saved on the server. To change a blob, a new one should be uploaded and the old UUID in the state replaced with the new one.

If an action would add a new blobId to the state, the blob should have previously been uploaded to the server.

A blob should only be downloaded on demand (lazy) and cached.

Synchronisation

  1. A client gets a snapshot of the state from the server via getState.
  2. Any time an action is applied on the server, it is sent to all clients via performAction and applied to them too. Due to the maintained packet ordering via a WebSocket and the fact that the synchronization of the state in the backend works synchronously, it is impossible for a client to receive actions out of order or receive actions already included in the state received by getState.
  3. A client can propose an action to the server via proposeAction.
  4. If the proposal was accepted, the action is applied on the server and sent to all clients via performAction.
  5. The server responds to a proposal with a response that indicates a success or rejection via an acknowledgment. A successful response is always sent after the performAction was broadcasted.

Optimistic updates

A consequence of the synchronization strategy described before is that it takes one roundtrip from the client to the server and back to get the correct state on the client that initiated the action. This can lead to a bad user experience because of high latency.

This is where optimistic updates come into play. We just assume optimistically that the proposed action will be applied on the server. Therefore we can apply the action on the client directly without waiting for a performAction from the server.

If the server rejects the proposal or a race condition occurs, the client corrects its state again. In our case, the optimisticActionHandler encapsulates this functionality.

The state in the frontend is not guaranteed to be correct. It is only guaranteed to automatically correct itself.

If you need to read from the state to change it, you should do this inside the action reducer because the currentState passed into a reducer is always guaranteed to be correct.

Performance considerations

  • Currently, every client maintains the whole state, and every action is sent to all clients. There is no way to only subscribe to a part of the state and only receive updates for that part.

Licenses and Attributions

Digital Fuesim MANV Copyright (C) 2023 See README.md#contributors for authors/contributors (bottom of this document).

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.

Some files are excluded to the mentioned license, read LICENSE-README.md for further information to which files these applies.

Keep in mind, that if you don't use docker you have to run npm run licensing:all before building the frontend to give users the option to download a copy of the source code of this software (and a list of attributions of third-parties, e.g. their libraries) or use another way that lets users download the source code of this software for free. If you didn't modify the source code, a link to this github repository is enough, but you can do both. If you run npm run deployment this command is already included.

Contributors


Lukas Hagen

💻 👀
Student 2022/23

Nils Hanff

💻 👀
Student 2022/23

Benildur Nickel

💻 👀
Student 2022/23

Lukas Radermacher

💻 👀
Student 2022/23

Julian Schmidt

💻 👀
Student 2021/22

Clemens Schielicke

💻 👀
Student 2021/22

Florian Krummrey

💻
Student 2021/22

Marvin Müller-Mettnau

💻 📦
Student 2021/22

Matthias Barkowsky

📆
Supervisor 2021-23

Christian Zöllner

📆
Supervisor 2021-23

digital-fuesim-manv's People

Contributors

anonym-hpi avatar benn02 avatar clfesc avatar dassderdie avatar dependabot[bot] avatar github-actions[bot] avatar greenscreen23 avatar hpistudent72 avatar lukasrad02 avatar nils1729 avatar web-flow avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

digital-fuesim-manv's Issues

Stress test

To validate our assumptions about the performance of our system we should try to test it in a real scenario as fast as possible. I propose shortly after the end of the first milestone.

  • on an experimental branch: add a button that proposes every second a (real) action after one joined a session
  • make a button that adds multiple patients instead of just one
  • build and host a webserver with our application build from this branch
  • an automated client joins the exercise and proposes an action every second
  • a real client joins the exercise and move stuff manually around (with optimistic updates enabled) - he can check the latency by seeing opening the website on another tab (that doesn't propose actions but only display the current state on the map).
  • figure out the upper limits of the server and clients

Parameters

  • number of real clients
  • number of automated clients
  • number of different devices
  • number of different networks (what about VPNs?)
  • time between sending an action and receiving the proposal
  • subjective smoothness
  • any problems?

Remove client from state on disconnect

The client should be removed from the state after its socket disconnects from the backend. This includes sending the appropriate action to all clients of the exercise.

Vulnerabilities in npm packages

We currently have some vulnerabilities in the frontend (run npm audit in the frontend to see them). We should

  • mitigate them by updating the affected packages, and
  • add auditing to the CI

in order to not get any bigger problems from them.

Add waiting room

A waiting room should be available where all joining participants first get to after joining. Trainer should not go there by default. The waiting room should contain a text informing the participants about the fact where they are.

Immutability types

Introduce the strict use of readonly into our codebase.

  • add Immutable, Mutable helpers and use them for the actions and state types as well as function parameters like in the reducers and the optimisticActionHandler.

  • I'm not sure about their use as interfaces yet, but that's easy to try out.

  • Maybe we could/should also introduce a JSON or PlainObject type (no Map/functions ...).

Setup/improve CI

This is a collection for all issues/TODOs/discussions relating the CI.
After the heavy lifting is done this can be closed and remaining (longer standing/less important) TODOs get their own issue.

TODOs

  1. Reuse build artifacts
  2. Is it even necessary to lint on windows and macos in addition to linux?

Map library

Features:

Must-have (creative alternatives as workarounds are ok):

  • zoom in and out (programmatically & mousewheel/pinch to zoom)
  • fixed viewport (maximum zoom, no panning outside the viewport), viewport has { latitude, longitude, width, height }
  • render elements (= vector graphics and raster graphics) on fixed geographical positions on the map
  • eventHandler for click or tap on an element
  • reposition an element on the map (click/tap & drag)
  • resize elements (click on a corner and drag)
  • drag an element on the map (click/tap & drag)
  • context-menus (right-click or long-press)
  • create edges between transferNodes
  • add inputs to these edges (e.g. input field for transferTime, ?viewport? name) - alternative: button that triggers a modal dialog
  • high quality satellite world map (able to zoom very far in)

Should-have:

  • grouping for svg elements (picture of a vehicle + status indicators + "button")

Nice-to-have:

  • calculate the time it takes to travel between two points
  • styling support (css like) for all library specific elements
  • eventHandler for hovering over elements
  • use a png instead of a map (or a custom map)

libraries to investigate (from openstreetmaps)

Route for joining an exercise

There should be a route, e.g. GET /join/:exerciseId that automatically (after asking for the display name) joins a client to the exercise provided by :exerciseId.

Tests fail

The tests still fail. I can only imagine that this is due to invalid caches. Maybe caching shared doesn't work as expected.

Possible synchronisation issue when retrieving the state

  • Add actionNr to performAction and getState to fix possible synchronisation issues

@Dassderdie
I just noticed a problem with our current API design:
The current idea is to first get the state and then all apply all the actions that we receive via "performAction". But there is no way of knowing which state we get and which actions were already applied.

I would therefore propose the following:

getState and performAction have a timestamp (or some other kind of number that gives them an order) in the answer from the backend.
The frontend

subscribes to performAction and saves the actions it receives
gets the State
Forgets all actions whose timestamp is before the timestamp of the state
Applies all the other actions in order
We would have to check whether a timestamp (Date.now()) is somehow security relevant...

@ClFeSc

I think we could just count the actions and return the action number of the last applied action with the state.

Look here for the original discussion

Add documentation about dependencies and devDependencies

The differentiation between devDependencies and normal dependencies is actually only relevant for libraries.
Non-library packages (like ours) can make arbitrary rules which go where.
I personally like to differentiate between runtime dependencies (dependencies) and those necessary for building, testing, etc. This convention is also recommended by angular as far as I know.
This makes it easier to spot whether e.g. a DOS vulnerability is affecting your runtime or only a package used for building/testing.

Originally posted by @Dassderdie in #47 (comment)

Jest starts backend unexpectedly

Jest starts the backend without us wanting it to. This required us to write some ugly singleton stuff in #47. We should look into preventing Jest from doing such things.

Cannot find module `digital-fuesim-manv-shared` or its corresponding type declarations.

I followed the steps outlined in README.md to setup the project on a clean system.

When I want to run the Start all task or run some tests I get running tests, the shared folders compiles without problems, but backend and frontend each show a buch of errors of the following kind:

Error: src/app/<SOME_CODE_FILE>.ts:<XX>:<YY> - error TS2307: 
Cannot find module 'digital-fuesim-manv-shared' or its corresponding type declarations.

Trying to delete all local node_modules and installing again did not help.

Ci fails on frontend tests

> [email protected] test
> jest --runInBand --coverage --verbose

PASS Frontend src/app/core/optimistic-action-handler.spec.ts
  OptimisticActionHandler
    ✓ should correctly apply not optimistic proposed actions when response is true (5 ms)
    ✓ should correctly apply not optimistic proposed actions when response is false (2 ms)
    ✓ should correctly perform actions (1 ms)
    ✓ should correctly apply optimistic actions (2 ms)
    ✓ should keep the right order when applying optimistic updates and performed updates (1 ms)
    ✓ should perform already proposed actions after the optimistic update is done (*** ms)

------------------------------|---------|----------|---------|---------|-------------------
File                          | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
------------------------------|---------|----------|---------|---------|-------------------
All files                     |     100 |      100 |     100 |     100 |                   
 optimistic-action-handler.ts |     100 |      100 |     100 |     100 |                   
------------------------------|---------|----------|---------|---------|-------------------

=============================== Coverage summary ===============================
Statements   : 100% ( ***/*** )
Branches     : 100% ( 4/4 )
Functions    : 100% ( 5/5 )
Lines        : 100% ( ***1/***1 )
================================================================================
Test Suites: 1 passed, 1 total
Tests:       6 passed, 6 total
Snapshots:   0 total
Time:        4.71*** s
Ran all test suites.
node:internal/event_target:777
  process.nextTick(() => { throw err; });
                           ^

Error: Unknown worker message type message
This is caused by either a bug in Node.js or incorrect usage of Node.js internals.
Please open an issue with this stack trace at https://github.com/nodejs/node/issues

    at new NodeError (node:internal/errors:***71:5)
    at Function.fail (node:internal/assert:20:9)
    at Worker.[kOnMessage] (node:internal/worker:***17:12)
    at MessagePort.<anonymous> (node:internal/worker:201:57)
    at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invokeTask (/home/runner/work/digital-fuesim-manv/digital-fuesim-manv/frontend/node_modules/zone.js/bundles/zone-testing-bundle.umd.js:441:***5)
    at Zone.Object.<anonymous>.Zone.runTask (/home/runner/work/digital-fuesim-manv/digital-fuesim-manv/frontend/node_modules/zone.js/bundles/zone-testing-bundle.umd.js:212:51)
    at ZoneTask.Object.<anonymous>.ZoneTask.invokeTask [as invoke] (/home/runner/work/digital-fuesim-manv/digital-fuesim-manv/frontend/node_modules/zone.js/bundles/zone-testing-bundle.umd.js:52***:***8)
    at invokeTask (/home/runner/work/digital-fuesim-manv/digital-fuesim-manv/frontend/node_modules/zone.js/bundles/zone-testing-bundle.umd.js:166***:18)
    at MessagePort.globalZoneAwareCallback (/home/runner/work/digital-fuesim-manv/digital-fuesim-manv/frontend/node_modules/zone.js/bundles/zone-testing-bundle.umd.js:1689:21)
    at MessagePort.[nodejs.internal.kHybridDispatch] (node:internal/event_target:562:20) {
  code: 'ERR_INTERNAL_ASSERTION'
}

Participant (Client) Overview

There should be an overview for all clients that is only visible to trainer. It should include a list of all clients, their roles and display names. Adding/removing a client to/from the waiting room should also be possible (if the waiting room already exists).

State management and synchronisation library

Requirements

Synchronisation between server/clients

  • a client can subscribe to a part of the state (example: all vehicles and personnel in viewport1 (= calculated via coordinates))
  • state should be robustly stored (backups) and handled (= database)
  • the state change can be executed without conflicts (e.g. a client changing the position of a vehicle during the state-update)
  • state changes should be validated by a trusted entity
  • a client gets updates to the state in real-time (e.g. "push" like websockets, no polling)

(local) State management client

  • in the client one should be able to subscribe to a part of the state (async observer pattern) and get snapshotted values directly in a synchronous way
  • nicely encapsulated client-side optimistic updates for more responsive ux

both

  • a client can modify the data and send the change to the server/the other clients
  • very good typings and reusability across all codebases (client and server)

TODOs

  • API design websockets
  • senden des States über websocket verbindung
  • backend ordentlich machen (file structure, watch mode)
  • action validation (@ClFeSc)
  • setup test frameworks
    • backend
    • shared
    • frontend unit tests
    • e2e
  • optimistic updates
  • Add actionNr to performAction and getState to fix possible synchronisation issues
  • Resolve all TODOs in the current code base

libraries to investigate

realtime database

client-side state management (stores)

Use Jest Monorepo features

As introduced in #47 the backend uses jest tests that currently fail due to our usage of ES modules for the shared library. We therefore had to set a node flag when running backend tests that resulted in the frontend tests failing. We then split up the test running into three separate calls to jest. These should be reunited, at least to allow a global coverage once again, and also better readability of the test output.

No notifications of vulnerabilities in dev

As dependabot only looks at the main branch its alerts are mostly outdated as we probably already have fixed some of those problems in dev, I'd suggest, additionally to Dependabot, to include auditing in the CI, as an ok-to-fail-job.

Different ids for exercises

Exercises should have two ids, one for participants, one for trainer. These ids should be used to determine whether a joining client should be a participant or a trainer. Also, only the trainer id should be deletable by DELETE /api/exercise/:exerciseId.

Run e2e tests in CI

We would have to:

  1. build the whole application
  2. start the frontend and backend
  3. run cypress
  4. after cypress is finished we have to kill the frontend and backend

Add client to state

We should add the client to the state of the exercise upon joining. This includes informing the other clients about the change, i.e. emit a performAction.

Cache eslint on CI

Store the info about processed files in order to only operate on the changed ones. The cache is stored in .eslintcache by default. Enabling this option can dramatically improve ESLint's running time by ensuring that only changed files are linted.
https://eslint.org/docs/user-guide/command-line-interface#--cache

This would probably be done the same as with angular #32 - so the cache is updated after each run.

Fix missing dependabot labels

As the title says, dependabot is currently set up to use labels that a) do not exist and b) are invalid label names.

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.