CI / Frontend - type-check & test (push) Canceled after 0s
비슷한 임시 연습곡 다섯 개를 교체했다. 부르크뮐러와 슈만 원본 30곡의 출처와 권리 정보를 보존했다. 각 MIDI에 양손 연습용 도입부와 마무리를 넣고 난이도를 음표 밀도로 분류했다. MIDI 구조 검사 30개와 서버 격리 테스트 5개를 통과했다. 운영 백업: /home/syskiller/piano/backups/bach-to-basics/20261009-practice-30-intro-ending. 백엔드만 운영에 반영했고 HTTPS 공개 목록과 30개 다운로드를 확인했다. 회원 업로드 2건은 보존됐다. 실제 건반 연주감 검사는 남아 있다.
36 lines
1.9 KiB
JavaScript
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}음`);
|
|
}
|