Vorschlag Datenstruktur Sphery Racer
...für die Kommunikation mit der online Rest-API
Stand 25. November 2020 - Julian Schönbächler
Inhalt
Login / Registrierung
Das Spiel wird ein Login-, sowie Registrierungsformular beinhalten. Die gesendeten Requests der Formulare beinhalten folgende Daten:
Registrierung
{
"username": "Christoph",
"email": "stophel@blocher.ch",
"password": "schlumpfgate"
}
Login
{
"email": "stophel@blocher.ch",
"password": "schlumpfgate"
}
Sync-Points im Spiel
Ausgehend vom jetzigen Spielaufbau und den aktuellen Anforderungen bezüglich der Kommunikation, sind 3 drei verschiedene Sync-Points vorgesehen, an welchen das Spiel mit der API interagiert.
Start der Session
Direkt nach dem Login und dem Erhalt des Authentifizierungs-Tokens und der Benutzer ID wird eine neue Spiel-Session gestartet.
Request
Das Spiel sendet folgenden Request:
{
"requestType": "session-start",
"requestTime": 1234567890,
"data": {
"loginAt": 1234567890,
"exercube": "SpheryCube1"
}
}
Key | Typ | Beschreibung |
---|---|---|
requestType | string |
Beschreibt den Typ des Requests |
requestTime | int |
Der Zeitstempel des Requests (Unix-Timestamp) |
data | {} |
Objekt mit den Request-spezifischen Daten |
→ loginAt | int |
Der Zeitstempel des Logins (Unix-Timestamp) |
→ exercube | string |
Die ID des ExerCubes |
Response
Als Antwort werden vom Server Benutzerspezifische Daten erwartet, welche für das Spiel erforderlich sind.
{
"session": {
"id": 1,
"healthData": <health-data>,
"workoutPresets": [...<workout>]
}
...
}
Key | Typ | Beschreibung |
---|---|---|
session | {} |
Objekt mit Session-spezifischen Daten |
→id | int |
Die ID der soeben gestarteten Session |
→ healthData | {} |
Spielerspezifische körperliche Daten (siehe: Health Data) |
→ workoutPresets | [] |
Ein Array an gespeicherten Workout Presets |
Info: Momentan werden keine "Workout Presets" gespeichert, sondern einfach die standard Workouts des Spiels verwendet. Der Wert für
workoutPresets
kann also immer ein leeres Array ([]
) sein.
Ende der Session
Direkt nach dem Login und dem Erhalt des Authentifizierungs-Tokens und der Benutzer ID wird eine neue Spiel-Session gestartet. Das Spiel sendet folgenden Request:
Request
{
"requestType": "session-close",
"requestTime": 1234567890,
"data": {
"logoutAt": 1234567890,
"sessionTime": 1800,
"netPromoterScore": 10
}
}
Key | Typ | Beschreibung |
---|---|---|
requestType | string |
Beschreibt den typ des Requests |
requestTime | int |
Der Zeitstempel des Requests (Unix-Timestamp) |
data | {} |
Objekt mit den Request-spezifischen Daten |
→ logoutAt | int |
Der Zeitstempel des Logouts (Unix-Timestamp) |
→ sessionTime | int |
Die Dauer der Session (in Sekunden) |
→ netPromoterScore | int |
Die Bewertung der Session [0-10] |
Response
Undefiniert
Abgeschlossenes Workout
Ein Workout beschreibt eigentlich immer ein einzelnes Rennen im Spiel. Nachdem der Spieler das Rennen beendet hat (sprich das Ziel erreicht hat), wird ein Request mit den gesamten Workout-Daten erstellt.
Request
{
"requestType": "workout-put",
"requestTime": 1234567890,
"data": {
"workout": <workout>,
"challenge": -1,
"duration": 600,
"hrTracking": true,
"hrAdaptivity": true,
"hrValues": [
{
"time": 3.02,
"value": 82
},
{
"time": 6.13,
"value": 83
},
...
],
"hrAverage": 163,
"hrMax": 199,
"score": 756388,
"maxCombo": 123,
"bodyScore": 0.9,
"brainScore": 0.8,
"dualflowScore": 0.85,
"exercises": [...<exercise>]
}
}
Key | Typ | Beschreibung |
---|---|---|
requestType | string |
Beschreibt den typ des Requests |
requestTime | int |
Der Zeitstempel des Requests (Unix-Timestamp) |
data | {} |
Objekt mit den Request-spezifischen Daten |
→ workout | int |
Workout data that was used for this workout (siehe Workout) |
→ challenge | int |
Die ID der Challenge mit welcher dieses Workout verlinkt ist; -1 falls keine Verlinkung besteht (momentan werden Challenges noch nicht gehandled, der Wert wird immer auf -1 gesetzt sein) |
→ duration | int |
Die effektive Trainingsdauer des Workouts (in Sekunden) |
→ hrTracking | bool |
Wurde die Herzrate getracked? |
→ hrAdaptivity | bool |
Wurde HR adaptiv gespielt? false für Performance adaptiv |
→ hrValues | [] |
Array von allen gemessenen HR-Werten; in der angegebenen Struktur - time = Zeit nach start des Workouts (in Sekunden)- value = HR-Wert |
→ hrAverage | int |
Die Durchschnittliche Herzrate über das ganze Workout gemessen |
→ hrMax | int |
Die tatsächlich erreichte maximale Herzrate |
→ score | int |
Die erreichte Punktzahl in diesem Workout |
→ maxCombo | int |
Maximum Combo, welcher erreicht wurde |
→ bodyScore | float |
Workout BodyScore (prozentualer Wert [0.0-1.0]) |
→ brainScore | float |
Workout BrainScore (prozentualer Wert [0.0-1.0]) |
→ dualflowScore | float |
Workout DualflowScore (prozentualer Wert [0.0-1.0]) |
→ exercises | [] |
Array, welches geordnet alle abgeschlossenen Übungen der Rennstrecke fasst (siehe Exercise) |
Response
Undefiniert
Allgemeine Datensätze
Hier werden alle Datensätze aufgeschlüsselt welche oft Inhalt der einzelnen Requests sein können und als eigene "Objekte" oder "Typen" gehandhabt werden.
Health Data
{
"hrRestingPulse": 80,
"hrReserve": 116,
"hrMax": 196,
"weight": 75,
"age": 30
}
Key | Typ | Beschreibung |
---|---|---|
hrRestingPulse | int |
Ruhepuls der HR; -1 falls undefiniert |
hrReserve | int |
Reservepuls der HR; -1 falls undefiniert |
hrMax | int |
HR Max; -1 falls undefiniert |
weight | int |
Gewicht (in kg); -1 falls undefiniert |
age | int |
Alter; -1 falls undefiniert |
Workout
{
"name": "MyCustomWorkout",
"race": {
"difficulty": 2,
"duration": 900,
"tutorial": false,
"startSpeed": 5,
"hrTarget": 0.9
},
"exercises": [
"touches",
"punches"
],
"tiers": [
{
"cognitiveChallenges": [
"mirror",
"lights"
],
"cognitiveMin": 0.0,
"cognitiveMax": 1.0,
"physicalMin": 0.0,
"physicalMax": 1.0
},
...
]
}
Key | Typ | Beschreibung |
---|---|---|
name | string |
Der Name (und ID; unique) des Workouts |
race | {} |
Renn-spezifische Daten |
→ difficulty | int |
Schwierigkeit des Rennens [0-2] |
→ duration | int |
Dauer des Rennens (in Sekunden) |
→ tutorial | bool |
Boxenstopp Tutorials verwendet? |
→ startSpeed | float |
Startgeschwindigkeit des Rennens [0.0-1.0] |
→ hrTarget | int |
Die Ziel-HR für HR-adaptives Spiel |
exercises | [...string] |
Array an Übungs-Typen welche für das Spiel ausgewählt wurden |
tiers | [...{}] |
Alle Combo-Tier informationen als Array; Länge des Arrays ist die Anzahl der Tiers |
→ cognitiveChallenges | [...string] |
Array an kognitiven Challenge-Typen welche für das Spiel ausgewählt wurden |
→ cognitiveMin | float |
Minimale kognitive Adaptivität [0.0-1.0] |
→ cognitiveMax | float |
Maximale kognitive Adaptivität [0.0-1.0] |
→ physicalMin | float |
Minimale physische Adaptivität [0.0-1.0] |
→ physicalMax | float |
Maximale physische Adaptivität [0.0-1.0] |
Exercise
{
"id": "midPunchLeft",
"name": "Punch Left",
"time": 2.14,
"tier": 2,
"precision": 3,
"score": 230
}
Key | Typ | Beschreibung |
---|---|---|
id | string |
Die ID (unique) der Übung |
name | string |
Der (human readable) Name der Übung |
time | float |
Die Zeit nach Start des Workouts nachdem die Übung passiert wurde |
tier | int |
Der Combo-Tier mit welchem die Übung passiert wurde |
precision | int |
Der Evaluierungswert der Übung (Anzahl Sterne; 0 falls fehlerhaft) |
score | int |
Die erhaltene Punktzahl für diese Übung |
Beispiele
Diese Beispiele zeigen wie jeweils ein voller Request für die oben beschriebenen Sync-Points am Ende strukturiert ist und aussehen könnte.
Start der Session
{
"requestType": "session-start",
"requestTime": 1606381769,
"data": {
"loginAt": 1606381767,
"exercube": "SpheryCube1"
}
}
Ende der Session
{
"requestType": "session-close",
"requestTime": 1606383628,
"data": {
"logoutAt": 1606383614,
"sessionTime": 1847,
"netPromoterScore": 8
}
}
Abgeschlossenes Workout
{
"requestType": "workout-put",
"requestTime": 1234567890,
"data": {
"workout": {
"name": "DualFlow",
"race": {
"difficulty": 2,
"duration": 900,
"tutorial": false,
"startSpeed": 5,
"hrTarget": 0.9
},
"exercises": [
"touches",
"punches"
],
"tiers": [
{
"cognitiveChallenges": [
"mirror",
"lights"
],
"cognitiveMin": 0.0,
"cognitiveMax": 1.0,
"physicalMin": 0.0,
"physicalMax": 1.0
},
{
"cognitiveChallenges": [
"audio",
"mirror"
],
"cognitiveMin": 0.3,
"cognitiveMax": 1.0,
"physicalMin": 0.5,
"physicalMax": 1.0
}
]
},
"challenge": -1,
"duration": 600,
"hrTracking": true,
"hrAdaptivity": true,
"hrValues": [
{
"time": 3.02,
"value": 82
},
{
"time": 6.13,
"value": 83
},
...
],
"hrAverage": 163,
"hrMax": 199,
"score": 756388,
"maxCombo": 123,
"bodyScore": 0.9,
"brainScore": 0.8,
"dualflowScore": 0.85,
"exercises": [
{
"id": "midPunchLeft",
"name": "Punch Left",
"time": 2.14,
"tier": 0,
"precision": 3,
"score": 60
},
{
"id": "lowTouchRight",
"name": "Low Touch Right",
"time": 5.72,
"tier": 0,
"precision": 2,
"score": 60
}
...
]
}
}