Files
ITOSMPiano-BachToBasics/scripts/check_practice_collection.mjs
T
이창현 8298f5af26
CI / Frontend - type-check & test (push) Canceled after 0s
서로 다른 연습곡 30개에 도입부와 마무리를 추가함
비슷한 임시 연습곡 다섯 개를 교체했다. 부르크뮐러와 슈만 원본 30곡의 출처와 권리 정보를 보존했다. 각 MIDI에 양손 연습용 도입부와 마무리를 넣고 난이도를 음표 밀도로 분류했다.

MIDI 구조 검사 30개와 서버 격리 테스트 5개를 통과했다. 운영 백업: /home/syskiller/piano/backups/bach-to-basics/20261009-practice-30-intro-ending. 백엔드만 운영에 반영했고 HTTPS 공개 목록과 30개 다운로드를 확인했다. 회원 업로드 2건은 보존됐다. 실제 건반 연주감 검사는 남아 있다.
2026-10-09 23:25:37 +09:00

36 lines
1.9 KiB
JavaScript

import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import midiPackage from '../frontend/node_modules/@tonejs/midi/build/Midi.js';
const { Midi } = midiPackage;
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'backend', 'sample_midi');
const collection = JSON.parse(fs.readFileSync(path.join(root, 'practice_collection.json'), 'utf8'));
if (collection.length !== 30 || new Set(collection.map((item) => item.title)).size !== 30) {
throw new Error('서로 다른 제목의 연습곡 30개가 필요합니다');
}
const motifs = new Set();
for (const item of collection) {
const midi = new Midi(fs.readFileSync(path.join(root, item.storage_name)));
const [right, left] = midi.tracks;
if (midi.tracks.length !== 2 || right.notes.length < 12 || left.notes.length < 6) {
throw new Error(`${item.storage_name}: 양손 음표가 부족합니다`);
}
if (midi.duration < 60 || midi.duration > 180) {
throw new Error(`${item.storage_name}: 곡 길이가 기준을 벗어납니다`);
}
if (right.notes[0].time < 0.4 || right.notes[4].time < 5 || left.notes[0].time !== 0) {
throw new Error(`${item.storage_name}: 도입부를 확인해야 합니다`);
}
if (midi.duration - right.notes.at(-1).time < 2.5 || midi.duration - left.notes.at(-1).time < 4) {
throw new Error(`${item.storage_name}: 마무리 지속 시간이 부족합니다`);
}
const motif = right.notes.slice(4, 20).map((note) => note.midi).join('-');
if (motifs.has(motif)) throw new Error(`${item.storage_name}: 다른 곡과 선율이 같습니다`);
motifs.add(motif);
if (![...right.notes, ...left.notes].every((note) => note.midi >= 21 && note.midi <= 108)) {
throw new Error(`${item.storage_name}: 피아노 음역을 벗어났습니다`);
}
console.log(`${item.storage_name}: ${midi.duration.toFixed(1)}초, 오른손 ${right.notes.length}음, 왼손 ${left.notes.length}음`);
}