From 255349fc95e58148f485a1fb3b7d7e7865bf338b Mon Sep 17 00:00:00 2001 From: Stian Fredrik Aune Date: Sun, 4 Sep 2022 19:43:21 +0200 Subject: [PATCH] Fix? --- webui-react/src/models/Programs.ts | 4 +- webui-react/src/pages/EditProgramPage.tsx | 2 +- webui-react/src/pages/PlayPage.tsx | 4 +- webui-react/src/pages/WorkoutPage.tsx | 13 ++++- webui-react/src/pages/runtime/ProgramBoi.tsx | 49 ++++++++++++++----- webui-react/vite.config.ts | 2 +- .../infrastructure/WorkoutExporter.kt | 2 +- .../git/ykonsole2/infrastructure/IConsole.kt | 28 ++++++++++- 8 files changed, 83 insertions(+), 21 deletions(-) diff --git a/webui-react/src/models/Programs.ts b/webui-react/src/models/Programs.ts index 5a1ffbc..2cd077f 100644 --- a/webui-react/src/models/Programs.ts +++ b/webui-react/src/models/Programs.ts @@ -15,9 +15,9 @@ export interface ProgramStep { export function weighting(step: ProgramStep) { if (step.duration) { if (step.duration.time) { - return 8 * step.duration.time; + return 4 * step.duration.time; } else if (step.duration.calories) { - return 4 * step.duration.calories; + return 8 * step.duration.calories; } else if (step.duration.distance) { return step.duration.distance; } diff --git a/webui-react/src/pages/EditProgramPage.tsx b/webui-react/src/pages/EditProgramPage.tsx index 4196831..15b41eb 100644 --- a/webui-react/src/pages/EditProgramPage.tsx +++ b/webui-react/src/pages/EditProgramPage.tsx @@ -56,7 +56,7 @@ export default function EditProgramPage() { programRepo().save({id, name, steps: newSteps}) .then(res => { if (res) { - navigate(program ? `/programs/${program.id}` : "/"); + navigate(program ? `/programs/${program.id}` : "/", {replace: !!program}); refreshPrograms(); } else { setWait(false); diff --git a/webui-react/src/pages/PlayPage.tsx b/webui-react/src/pages/PlayPage.tsx index 22a73a2..4cb07ac 100644 --- a/webui-react/src/pages/PlayPage.tsx +++ b/webui-react/src/pages/PlayPage.tsx @@ -183,7 +183,9 @@ function RunPlayPage(): JSX.Element { {lastState && ( - + + +

diff --git a/webui-react/src/pages/WorkoutPage.tsx b/webui-react/src/pages/WorkoutPage.tsx index 62d669b..693c3ff 100644 --- a/webui-react/src/pages/WorkoutPage.tsx +++ b/webui-react/src/pages/WorkoutPage.tsx @@ -32,9 +32,18 @@ export default function WorkoutPage(): JSX.Element { const states = useMemo(() => getStates(id || "random"), [getStates, id]); const [expanded, setExpanded] = useState(false); + const ratio = useMemo(() => { + if (expanded || !states) return 1; + + if (states.length > 1800) return 300; + if (states.length > 900) return 60; + if (states.length > 300) return 30; + return 15; + }, [expanded, states]); + const wsFilter = useCallback((ws: WorkoutState, index: number, arr: WorkoutState[]) => { - return expanded || (ws.time % 15 === 0) || index === arr.length - 1; - }, [expanded]); + return (ws.time % ratio === 0) || index === arr.length - 1; + }, [ratio]); useEffect(() => { fetchWorkout(id || "random"); diff --git a/webui-react/src/pages/runtime/ProgramBoi.tsx b/webui-react/src/pages/runtime/ProgramBoi.tsx index 95086bb..e61e01a 100644 --- a/webui-react/src/pages/runtime/ProgramBoi.tsx +++ b/webui-react/src/pages/runtime/ProgramBoi.tsx @@ -16,15 +16,47 @@ interface ProgressState { currentIndex: number lastTransition: WorkoutState lastValue: WorkoutState - toNext: { current: number, max: number } + toNext: ToNext stopped: boolean } +interface ToNext { + current: number, + max: number, +} + interface ProgressChange { skip?: boolean workoutState?: WorkoutState } +function calculateToNext( + step: ProgramStep & StepMeta, + lastValue: WorkoutState, + lastTransition: WorkoutState, +): ToNext { + if (step.duration) { + if (step.duration.time) { + return { + current: lastValue.time - lastTransition.time, + max: step.duration.time, + }; + } else if (step.duration.calories && lastTransition.calories !== undefined && lastValue.calories !== undefined) { + return { + current: lastValue.calories - lastTransition.calories, + max: step.duration.calories, + }; + } else if (step.duration.distance && lastTransition.distance !== undefined && lastValue.distance !== undefined) { + return { + current: lastValue.distance - lastTransition.distance, + max: step.duration.distance, + }; + } + } + + throw new Error("Illegal state"); +} + function programReducer(state: ProgressState, change: ProgressChange) { let {steps, currentIndex, lastTransition, lastValue, toNext, stopped} = state; @@ -53,21 +85,16 @@ function programReducer(state: ProgressState, change: ProgressChange) { const step = steps[currentIndex]; if (step.duration) { - if (step.duration.time) { - toNext.current = lastValue.time - lastTransition.time; - toNext.max = step.duration.time; - } else if (step.duration.calories && lastTransition.calories !== undefined && lastValue.calories !== undefined) { - toNext.current = lastValue.calories - lastTransition.calories; - toNext.max = step.duration.calories; - } else if (step.duration.distance && lastTransition.distance !== undefined && lastValue.distance !== undefined) { - toNext.current = lastValue.distance - lastTransition.distance; - toNext.max = step.duration.distance; - } + toNext = calculateToNext(step, lastValue, lastTransition); if (toNext.current >= toNext.max) { steps[currentIndex].actualDuration = diffLinearValues(lastValue, lastTransition); currentIndex += 1; lastTransition = lastValue; + + if (currentIndex < steps.length) { + toNext = calculateToNext(steps[currentIndex], lastValue, lastTransition); + } } } } diff --git a/webui-react/vite.config.ts b/webui-react/vite.config.ts index fd77125..b8c2295 100644 --- a/webui-react/vite.config.ts +++ b/webui-react/vite.config.ts @@ -15,7 +15,7 @@ export default ({mode}) => { server: { proxy: { "/api": { - target: 'http://localhost:8080', + target: 'http://localhost:9301', changeOrigin: true, }, } diff --git a/ykonsole-exporter/src/main/kotlin/net/aiterp/git/ykonsole2/infrastructure/WorkoutExporter.kt b/ykonsole-exporter/src/main/kotlin/net/aiterp/git/ykonsole2/infrastructure/WorkoutExporter.kt index 45f4243..db83aeb 100644 --- a/ykonsole-exporter/src/main/kotlin/net/aiterp/git/ykonsole2/infrastructure/WorkoutExporter.kt +++ b/ykonsole-exporter/src/main/kotlin/net/aiterp/git/ykonsole2/infrastructure/WorkoutExporter.kt @@ -29,7 +29,7 @@ class WorkoutExporter( override suspend fun start(input: FlowBus, output: FlowBus) { log.info("Checking recent workouts...") - val yesterday = Instant.now().minus(24, ChronoUnit.HOURS) + val yesterday = Instant.now().minus(1, ChronoUnit.HOURS) for (workout in workoutRepo.fetchAll().filter { it.createdAt > yesterday }) { export(workout) } diff --git a/ykonsole-iconsole/src/main/kotlin/net/aiterp/git/ykonsole2/infrastructure/IConsole.kt b/ykonsole-iconsole/src/main/kotlin/net/aiterp/git/ykonsole2/infrastructure/IConsole.kt index 2412625..155b897 100644 --- a/ykonsole-iconsole/src/main/kotlin/net/aiterp/git/ykonsole2/infrastructure/IConsole.kt +++ b/ykonsole-iconsole/src/main/kotlin/net/aiterp/git/ykonsole2/infrastructure/IConsole.kt @@ -8,6 +8,7 @@ import net.aiterp.git.ykonsole2.domain.runtime.* import net.aiterp.git.ykonsole2.infrastructure.drivers.abstracts.ActiveDriver import net.aiterp.git.ykonsole2.infrastructure.iconsole.* import net.aiterp.git.ykonsole2.application.logging.log +import java.time.Instant import java.util.* import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds @@ -20,7 +21,11 @@ class IConsole : ActiveDriver() { private var running = false private var connected = false + private var tryingSince: Instant? = null + private var maxLevel = 20 + private var lastCals = 0 + private var lastMeters = 0 private val queue = Collections.synchronizedSet(LinkedHashSet()) @@ -30,6 +35,8 @@ class IConsole : ActiveDriver() { private var btCommandInput: BluetoothGattCharacteristic? = null private fun onConnect(device: Device, output: FlowBus) { + tryingSince = Instant.now() + if (!device.connectionString.startsWith("iconsole:")) { logger.info("Ignoring non-iConsole $device") return @@ -112,10 +119,13 @@ class IConsole : ActiveDriver() { if (currentTime > lastTime) { lastTime = currentTime + lastCals = maxOf(res.calories, lastCals) + lastMeters = maxOf((res.distance * 1000).toInt(), lastMeters) + output.emitBlocking(ValuesReceived(listOf( Time(lastTime), - Calories(res.calories), - Distance((res.distance * 1000).toInt()), + Calories(lastCals), + Distance(lastMeters), Level(res.level), ))) } @@ -130,11 +140,23 @@ class IConsole : ActiveDriver() { override fun onScanStopped() { logger.info("Scan stopped") + + tryingSince?.let { ts -> + if (ts.isBefore(Instant.now().minusSeconds(20))) { + central?.stopScan() + tryingSince = null + runBlocking { + output.emit(ErrorOccurred("Connection timeout after 20 seconds")) + output.emit(Disconnected) + } + } + } } override fun onDiscoveredPeripheral(peripheral: BluetoothPeripheral, scanResult: ScanResult) { logger.info("Connecting to ${peripheral.name} (${peripheral.address})...") + tryingSince = null central?.connectPeripheral(peripheral, cbPeripheral) central?.stopScan() } @@ -154,6 +176,8 @@ class IConsole : ActiveDriver() { private fun onDisconnect() { lastTime = 0 + lastCals = 0 + lastMeters = 0 running = false connected = false