File size: 3,040 Bytes
6f1c297
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import { regulateWithBeadSolver, starry } from 'starry-omr';
import * as issueMeasureService from '../services/issueMeasure.service.js';
import * as scoreService from '../services/score.service.js';
import { DbSolutionStore } from './dbSolutionStore.js';
import { getPickers } from './regulation.js';
import { broadcast, getSession, removeSession } from './regulationRegistry.js';

export async function regulateScoreWithProgress(scoreId: string): Promise<void> {
	const session = getSession(scoreId);

	try {
		// 1. Read score from DB
		const scoreRow = await scoreService.getScore(scoreId);
		if (!scoreRow) throw new Error(`Score not found: ${scoreId}`);

		const scoreData = scoreRow.data;
		if (!scoreData) throw new Error(`Score has no data: ${scoreId}`);

		// 2. Recover with starry
		const score = starry.recoverJSON(scoreData, starry);

		// 3. Get pickers
		const pickers = getPickers();
		if (!pickers) throw new Error('Regulation not initialized — no pickers loaded');

		// Count total measures for progress tracking
		score.assemble();
		const spartito = score.makeSpartito();
		const totalMeasures = spartito.measures.length;
		// Discard this spartito — regulateWithBeadSolver creates its own
		score.spartito = undefined;

		if (session) session.total = totalMeasures;
		broadcast(scoreId, { type: 'started', scoreId, totalMeasures });

		// 4. Call regulateWithBeadSolver
		const stat = await regulateWithBeadSolver(score, {
			pickers,
			solutionStore: DbSolutionStore,
			onPassStart: (pass, conditionName, pendingCount) => {
				const s = getSession(scoreId);
				if (s) {
					s.pass = pass;
					s.remaining = pendingCount;
					s.total = totalMeasures;
				}
				broadcast(scoreId, {
					type: 'progress',
					scoreId,
					pass,
					remaining: pendingCount,
					total: totalMeasures,
					measureIndex: -1,
					better: false,
					fine: false,
					error: false,
				});
			},
			onProgress: (measure, evaluation, better, { pass, remaining, total }) => {
				const s = getSession(scoreId);
				if (s) {
					s.pass = pass;
					s.remaining = remaining;
					s.total = total;
				}
				broadcast(scoreId, {
					type: 'progress',
					scoreId,
					pass,
					remaining,
					total,
					measureIndex: (measure as any).measureIndex,
					better,
					fine: evaluation.fine,
					error: evaluation.error,
				});
			},
			onSaveIssueMeasure: (data) => {
				issueMeasureService
					.upsert(scoreId, data.measureIndex, new starry.EditableMeasure(data.measure), data.status)
					.catch((err: any) => console.error('[regulateWithProgress] failed to save issue measure:', err));
			},
		});

		// 5. Save regulated score back to DB
		await scoreService.updateScore(scoreId, { data: (score as any).toJSON() });

		// 6. Broadcast completed
		broadcast(scoreId, { type: 'completed', scoreId, stat });
	} catch (err: any) {
		console.error('[regulateWithProgress] error:', err);
		broadcast(scoreId, { type: 'error', scoreId, message: err.message || String(err) });
	} finally {
		removeSession(scoreId);
	}
}