Files
ITOSMPiano-BachToBasics/scripts/check_beginner_midis.mjs
T
이창현 89f66c3bee
CI / Frontend - type-check & test (push) Canceled after 0s
초보자용 1분 양손 MIDI 연습곡 다섯 개를 추가함
직접 만든 연습곡 다섯 파일을 공개 보관함에 등록했다. 별빛 계단은 입문과 쉬움 두 단계로 제공한다.

MIDI 파서 검사와 백엔드 단위 테스트 5개를 통과했다. 운영 백업은 /home/syskiller/piano/backups/bach-to-basics/20261009-beginner-midi 에 있다. 백엔드만 갱신했고 비회원 목록과 다운로드를 확인했다. 실제 USB MIDI 장치 검사는 남아 있다. 사전 훅은 로컬 pnpm 의존성 불일치로 실행되지 않아 관련 검사를 직접 수행했다.
2026-10-09 23:06:17 +09:00

33 lines
1.4 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 expected = [
["starlight-steps-beginner.mid", 4],
["starlight-steps-easy.mid", 4],
["evening-waltz-beginner.mid", 3],
["sunrise-arpeggio-easy.mid", 4],
["black-key-pentatonic-beginner.mid", 4],
];
for (const [name, meter] of expected) {
const midi = new Midi(fs.readFileSync(path.join(root, name)));
const [right, left] = midi.tracks;
if (midi.tracks.length !== 2 || !right?.notes.length || !left?.notes.length) {
throw new Error(`${name}: 오른손과 왼손 트랙이 각각 필요합니다`);
}
if (midi.duration < 60 || midi.duration > 90) {
throw new Error(`${name}: 곡 길이가 1분에서 1분 30초 사이여야 합니다 (${midi.duration.toFixed(1)}초)`);
}
if (midi.header.timeSignatures[0]?.timeSignature[0] !== meter) {
throw new Error(`${name}: 박자가 일치하지 않습니다`);
}
if ([...right.notes, ...left.notes].some((note) => note.midi < 21 || note.midi > 108)) {
throw new Error(`${name}: 피아노 음역을 벗어났습니다`);
}
console.log(`${name}: ${midi.duration.toFixed(1)}초, 오른손 ${right.notes.length}음, 왼손 ${left.notes.length}음`);
}