87 lines
2.8 KiB
TypeScript
87 lines
2.8 KiB
TypeScript
import { Bar, Course } from 'tja-parser';
|
|
|
|
export interface Factors {
|
|
physical_density: number;
|
|
stamina_requirement: number;
|
|
pattern_complexity: number;
|
|
rhythmic_complexity: number;
|
|
reading_gimmick: number;
|
|
}
|
|
|
|
export namespace Factor {
|
|
export function getAllNotes(course: Course): any[] {
|
|
const notes: any[] = [];
|
|
for (const group of course.noteGroups) {
|
|
if (group instanceof Bar) {
|
|
notes.push(...group.getNotes());
|
|
}
|
|
}
|
|
return notes;
|
|
}
|
|
|
|
export function getPhysicalDensity(course: Course): number {
|
|
const notes = getAllNotes(course);
|
|
if (notes.length === 0) return 0;
|
|
const bars = course.noteGroups.length;
|
|
return notes.length / (bars || 1);
|
|
}
|
|
|
|
export function getStaminaRequirement(course: Course): number {
|
|
const notes = getAllNotes(course);
|
|
let maxStream = 0;
|
|
let currentStream = 0;
|
|
|
|
for (const note of notes) {
|
|
if (note.type !== '0') {
|
|
currentStream++;
|
|
} else {
|
|
maxStream = Math.max(maxStream, currentStream);
|
|
currentStream = 0;
|
|
}
|
|
}
|
|
return Math.max(maxStream, currentStream) / 100;
|
|
}
|
|
|
|
export function getPatternComplexity(course: Course): number {
|
|
const notes = getAllNotes(course).filter(n => n.type === '1' || n.type === '2');
|
|
let transitions = 0;
|
|
|
|
for (let i = 1; i < notes.length; i++) {
|
|
if (notes[i].type !== notes[i-1].type) {
|
|
transitions++;
|
|
}
|
|
}
|
|
return notes.length > 0 ? transitions / notes.length : 0;
|
|
}
|
|
|
|
export function getRhythmicComplexity(course: Course): number {
|
|
let complexNotes = 0;
|
|
const allNotes = getAllNotes(course);
|
|
for (const group of course.noteGroups) {
|
|
if (group instanceof Bar) {
|
|
const division = group.getNotes().length;
|
|
if (division % 4 !== 0 || division > 16) {
|
|
complexNotes += division;
|
|
}
|
|
}
|
|
}
|
|
return allNotes.length > 0 ? complexNotes / allNotes.length : 0;
|
|
}
|
|
|
|
export function getReadingGimmick(course: Course): number {
|
|
// BPM 변화나 Scroll 변화 빈도 측정
|
|
// tja-parser의 구조에 따라 구현 (여기서는 placeholder)
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
export function factorize(course: Course): Factors {
|
|
return {
|
|
physical_density: Factor.getPhysicalDensity(course),
|
|
stamina_requirement: Factor.getStaminaRequirement(course),
|
|
pattern_complexity: Factor.getPatternComplexity(course),
|
|
rhythmic_complexity: Factor.getRhythmicComplexity(course),
|
|
reading_gimmick: Factor.getReadingGimmick(course)
|
|
};
|
|
}
|