adds raw power metric and memory cleanup in games

This commit is contained in:
Lars Berning 2022-02-16 20:04:49 +01:00
parent 63216b1159
commit cb4b2d831f
No known key found for this signature in database
GPG Key ID: 028E73C9E1D8A0B3
8 changed files with 60 additions and 15 deletions

View File

@ -41,6 +41,7 @@ export function createRowingGames (canvasElement, clientWidth, clientHeight) {
// todo: check if there is some kaboomish way to get the active scene
let activeScene
k.scene('strokeFighterBattle', () => { activeScene = StrokeFighterBattleScene(k) })
k.scene('disposed', () => { })
k.go('strokeFighterBattle')
@ -50,8 +51,15 @@ export function createRowingGames (canvasElement, clientWidth, clientHeight) {
}
}
// todo: currently we move to an empty scene to dispose the game as there does not seem to be
// a mechanism in kaboom to dispose the instance.
function dispose () {
k.go('disposed')
}
return {
k,
dispose,
appState
}
}

View File

@ -182,17 +182,34 @@ export default function StrokeFighterBattleScene (k) {
})
const timer = k.add([
k.text('0'),
k.text('00:00'),
k.scale(0.8),
k.pos(12, 32),
k.fixed(),
k.layer('ui')
])
let trainingTimeRounded = 0
timer.onUpdate(() => {
trainingTime += k.dt()
timer.text = trainingTime.toFixed(2)
const newTrainingTimeRounded = Math.round(trainingTime)
if (trainingTimeRounded !== newTrainingTimeRounded) {
timer.text = `${secondsToTimeString(newTrainingTimeRounded)} / ${k.debug.fps()}fps`
trainingTimeRounded = newTrainingTimeRounded
}
})
// converts a timestamp in seconds to a human readable hh:mm:ss format
function secondsToTimeString (secondsTimeStamp) {
if (secondsTimeStamp === Infinity) return '∞'
const hours = Math.floor(secondsTimeStamp / 60 / 60)
const minutes = Math.floor(secondsTimeStamp / 60) - (hours * 60)
const seconds = Math.floor(secondsTimeStamp % 60)
let timeString = hours > 0 ? ` ${hours.toString().padStart(2, '0')}:` : ''
timeString += `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
return timeString
}
k.onCollide('bullet', 'enemy', (bullet, enemy) => {
k.destroy(bullet)
enemy.hurt(1)
@ -218,9 +235,9 @@ export default function StrokeFighterBattleScene (k) {
}
function driveFinished (metrics) {
if (metrics.power < THRESHOLD_POWER * 0.75) {
if (metrics.powerRaw < THRESHOLD_POWER * 0.75) {
fireWeapons(1)
} else if (metrics.power < THRESHOLD_POWER) {
} else if (metrics.powerRaw < THRESHOLD_POWER) {
fireWeapons(2)
} else {
fireWeapons(3)

View File

@ -92,4 +92,10 @@ export class GameComponent extends AppElement {
}
}
}
disconnectedCallback () {
if (this.rowingGames !== undefined) {
this.rowingGames.dispose()
}
}
}

View File

@ -8,9 +8,6 @@
import NoSleep from 'nosleep.js'
import { filterObjectByKeys } from './helper.js'
const rowingMetricsFields = ['strokesTotal', 'distanceTotal', 'caloriesTotal', 'power', 'heartrate',
'heartrateBatteryLevel', 'splitFormatted', 'strokesPerMinute', 'durationTotalFormatted', 'strokeState']
export function createApp (app) {
const urlParameters = new URLSearchParams(window.location.search)
const mode = urlParameters.get('mode')
@ -74,13 +71,9 @@ export function createApp (app) {
break
}
case 'metrics': {
let activeFields = rowingMetricsFields
const resetStateFields = ['heartrate', 'heartrateBatteryLevel']
// if we are in reset state only update heart rate
if (data.strokesTotal === 0) {
activeFields = ['heartrate', 'heartrateBatteryLevel']
}
const filteredData = filterObjectByKeys(data, activeFields)
const filteredData = (data.strokesTotal === 0) ? filterObjectByKeys(data, resetStateFields) : data
app.updateState({ ...app.getState(), metrics: filteredData })
break
}

View File

@ -158,6 +158,7 @@ function createRowingStatistics (config) {
strokeTime: lastStrokeDuration, // seconds
distance: lastStrokeDistance > 0 && lastStrokeSpeed > 0 && sessionState === 'rowing' ? lastStrokeDistance : 0, // meters
power: powerAverager.getAverage() > 0 && lastStrokeSpeed > 0 && sessionState === 'rowing' ? powerAverager.getAverage() : 0, // watts
powerRaw: powerAverager.getLastPushedValue() > 0 && lastStrokeSpeed > 0 && sessionState === 'rowing' ? powerAverager.getLastPushedValue() : 0, // watts
split: splitTime, // seconds/500m
splitFormatted: secondsToTimeString(splitTime),
powerRatio: powerRatioAverager.getAverage() > 0 && lastStrokeSpeed > 0 && sessionState === 'rowing' ? powerRatioAverager.getAverage() : 0,

View File

@ -29,6 +29,10 @@ function createWeightedAverager (maxNumOfDataPoints) {
}
}
function getLastPushedValue () {
return dataPoints[0]
}
function reset () {
dataPoints = []
}
@ -36,6 +40,7 @@ function createWeightedAverager (maxNumOfDataPoints) {
return {
pushValue,
getAverage,
getLastPushedValue,
reset
}
}

View File

@ -25,6 +25,22 @@ test('average of a and b is (2*b + a) / 3', () => {
assert.is(weightedAverager.getAverage(), 3)
})
test('average of a, b and c is (2*c + b) / 3 if maxNumOfDataPoints is 2', () => {
const weightedAverager = createWeightedAverager(2)
weightedAverager.pushValue(5) // a
weightedAverager.pushValue(2) // b
weightedAverager.pushValue(17) // c
assert.is(weightedAverager.getAverage(), 12)
})
test('lastPushedValue of a, b and c is c', () => {
const weightedAverager = createWeightedAverager(10)
weightedAverager.pushValue(5) // a
weightedAverager.pushValue(2) // b
weightedAverager.pushValue(17) // c
assert.is(weightedAverager.getLastPushedValue(), 17)
})
test('average should be 0 after reset', () => {
const weightedAverager = createWeightedAverager(10)
weightedAverager.pushValue(5)

View File

@ -37,14 +37,13 @@ export default {
terser({
ecma: 2020,
module: true,
warnings: true,
mangle: {
properties: {
regex: /^__/
}
}
}),
summary()
summary({})
],
output:
{