mirror of
https://github.com/jhbruhn/respira.git
synced 2026-01-27 10:23:41 +00:00
fix: Calculate time correctly per color block using Brother formula
Implemented proper time calculation matching the Brother app algorithm: - 150ms per stitch + 3000ms startup time per color block - Calculate total and elapsed time by summing across color blocks - This fixes the "999 seconds" issue by calculating time accurately Created timeCalculation utility with: - convertStitchesToMinutes: Convert stitches to minutes using PP1 formula - calculatePatternTime: Calculate total/elapsed time per color blocks Updated ProgressMonitor to show: - Total Time (calculated from all color blocks) - Elapsed Time / Total Time (based on current stitch position) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
f2d05c2714
commit
bc46fe0015
2 changed files with 81 additions and 6 deletions
|
|
@ -21,6 +21,7 @@ import {
|
||||||
canResumeSewing,
|
canResumeSewing,
|
||||||
getStateVisualInfo,
|
getStateVisualInfo,
|
||||||
} from "../utils/machineStateHelpers";
|
} from "../utils/machineStateHelpers";
|
||||||
|
import { calculatePatternTime } from "../utils/timeCalculation";
|
||||||
|
|
||||||
export function ProgressMonitor() {
|
export function ProgressMonitor() {
|
||||||
// Machine store
|
// Machine store
|
||||||
|
|
@ -109,6 +110,15 @@ export function ProgressMonitor() {
|
||||||
currentStitch >= block.startStitch && currentStitch < block.endStitch,
|
currentStitch >= block.startStitch && currentStitch < block.endStitch,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Calculate time based on color blocks (matches Brother app calculation)
|
||||||
|
const { totalMinutes, elapsedMinutes } = useMemo(() => {
|
||||||
|
if (colorBlocks.length === 0) {
|
||||||
|
return { totalMinutes: 0, elapsedMinutes: 0 };
|
||||||
|
}
|
||||||
|
const result = calculatePatternTime(colorBlocks, currentStitch);
|
||||||
|
return { totalMinutes: result.totalMinutes, elapsedMinutes: result.elapsedMinutes };
|
||||||
|
}, [colorBlocks, currentStitch]);
|
||||||
|
|
||||||
// Auto-scroll to current block
|
// Auto-scroll to current block
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentBlockRef.current) {
|
if (currentBlockRef.current) {
|
||||||
|
|
@ -185,11 +195,10 @@ export function ProgressMonitor() {
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-gray-50 dark:bg-gray-700/50 p-2 rounded">
|
<div className="bg-gray-50 dark:bg-gray-700/50 p-2 rounded">
|
||||||
<span className="text-gray-600 dark:text-gray-400 block">
|
<span className="text-gray-600 dark:text-gray-400 block">
|
||||||
Est. Time
|
Total Time
|
||||||
</span>
|
</span>
|
||||||
<span className="font-semibold text-gray-900 dark:text-gray-100">
|
<span className="font-semibold text-gray-900 dark:text-gray-100">
|
||||||
{Math.floor(patternInfo.totalTime / 60)}:
|
{totalMinutes} min
|
||||||
{String(patternInfo.totalTime % 60).padStart(2, "0")}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-gray-50 dark:bg-gray-700/50 p-2 rounded">
|
<div className="bg-gray-50 dark:bg-gray-700/50 p-2 rounded">
|
||||||
|
|
@ -225,11 +234,10 @@ export function ProgressMonitor() {
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-gray-50 dark:bg-gray-700/50 p-2 rounded">
|
<div className="bg-gray-50 dark:bg-gray-700/50 p-2 rounded">
|
||||||
<span className="text-gray-600 dark:text-gray-400 block">
|
<span className="text-gray-600 dark:text-gray-400 block">
|
||||||
Time Elapsed
|
Time
|
||||||
</span>
|
</span>
|
||||||
<span className="font-semibold text-gray-900 dark:text-gray-100">
|
<span className="font-semibold text-gray-900 dark:text-gray-100">
|
||||||
{Math.floor(sewingProgress.currentTime / 60)}:
|
{elapsedMinutes} / {totalMinutes} min
|
||||||
{String(sewingProgress.currentTime % 60).padStart(2, "0")}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
67
src/utils/timeCalculation.ts
Normal file
67
src/utils/timeCalculation.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
/**
|
||||||
|
* Convert stitch count to minutes using Brother PP1 timing formula
|
||||||
|
* Formula: ((pointCount - 1) * 150 + 3000) / 60000
|
||||||
|
* - 150ms per stitch
|
||||||
|
* - 3000ms startup time
|
||||||
|
* - Result in minutes (rounded up)
|
||||||
|
*/
|
||||||
|
export function convertStitchesToMinutes(stitchCount: number): number {
|
||||||
|
if (stitchCount <= 1) return 0;
|
||||||
|
|
||||||
|
const timeMs = (stitchCount - 1) * 150 + 3000;
|
||||||
|
const timeMin = Math.ceil(timeMs / 60000);
|
||||||
|
|
||||||
|
return timeMin < 1 ? 1 : timeMin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate total and elapsed time for a pattern based on color blocks
|
||||||
|
* This matches the Brother app's calculation method
|
||||||
|
*/
|
||||||
|
export function calculatePatternTime(
|
||||||
|
colorBlocks: Array<{ stitchCount: number }>,
|
||||||
|
currentStitch: number
|
||||||
|
): {
|
||||||
|
totalMinutes: number;
|
||||||
|
elapsedMinutes: number;
|
||||||
|
remainingMinutes: number;
|
||||||
|
} {
|
||||||
|
let totalMinutes = 0;
|
||||||
|
let elapsedMinutes = 0;
|
||||||
|
let cumulativeStitches = 0;
|
||||||
|
|
||||||
|
// Calculate time per color block
|
||||||
|
for (const block of colorBlocks) {
|
||||||
|
totalMinutes += convertStitchesToMinutes(block.stitchCount);
|
||||||
|
cumulativeStitches += block.stitchCount;
|
||||||
|
|
||||||
|
if (cumulativeStitches < currentStitch) {
|
||||||
|
// This entire block is completed
|
||||||
|
elapsedMinutes += convertStitchesToMinutes(block.stitchCount);
|
||||||
|
} else if (cumulativeStitches === currentStitch) {
|
||||||
|
// We just completed this block
|
||||||
|
elapsedMinutes += convertStitchesToMinutes(block.stitchCount);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// We're partway through this block
|
||||||
|
const stitchesInBlock = currentStitch - (cumulativeStitches - block.stitchCount);
|
||||||
|
elapsedMinutes += convertStitchesToMinutes(stitchesInBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
totalMinutes,
|
||||||
|
elapsedMinutes,
|
||||||
|
remainingMinutes: Math.max(0, totalMinutes - elapsedMinutes),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format minutes as MM:SS
|
||||||
|
*/
|
||||||
|
export function formatMinutes(minutes: number): string {
|
||||||
|
const mins = Math.floor(minutes);
|
||||||
|
const secs = Math.round((minutes - mins) * 60);
|
||||||
|
return `${mins}:${String(secs).padStart(2, '0')}`;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue