58 lines
1.8 KiB
TypeScript
58 lines
1.8 KiB
TypeScript
import type { SectionId } from '@/content/types';
|
|
import type {
|
|
AudioJourneyState,
|
|
ChapterIntent,
|
|
DriveEnergySample,
|
|
MusicMood,
|
|
} from '@/audio/types';
|
|
|
|
const JOURNEY_MUSIC = Object.freeze({
|
|
start: { mood: 'open', entryPhrase: 0 },
|
|
profile: { mood: 'open', entryPhrase: 1 },
|
|
experience: { mood: 'shadow', entryPhrase: 2 },
|
|
infrastructure: { mood: 'shadow', entryPhrase: 3 },
|
|
'selected-builds': { mood: 'lift', entryPhrase: 4 },
|
|
'additional-work': { mood: 'lift', entryPhrase: 5 },
|
|
toolkit: { mood: 'resolve', entryPhrase: 6 },
|
|
contact: { mood: 'resolve', entryPhrase: 7 },
|
|
} as const satisfies Readonly<Record<
|
|
SectionId,
|
|
{ readonly mood: MusicMood; readonly entryPhrase: number }
|
|
>>);
|
|
|
|
export function resolveChapterIntent(
|
|
sectionId: SectionId,
|
|
generation = 0,
|
|
): ChapterIntent {
|
|
const chapter = JOURNEY_MUSIC[sectionId];
|
|
return Object.freeze({
|
|
sectionId,
|
|
mood: chapter.mood,
|
|
atStart: sectionId === 'start',
|
|
entryPhrase: chapter.entryPhrase,
|
|
generation: Math.max(0, Math.trunc(generation)),
|
|
});
|
|
}
|
|
|
|
export const DEFAULT_CHAPTER_INTENT = resolveChapterIntent('start');
|
|
export const DEFAULT_DRIVE_ENERGY = Object.freeze({
|
|
energy: 0,
|
|
source: 'idle',
|
|
} as const satisfies DriveEnergySample);
|
|
|
|
export function resolveJourneyMusicState(sectionId: string, intensity = 0): AudioJourneyState {
|
|
const canonicalId = Object.hasOwn(JOURNEY_MUSIC, sectionId)
|
|
? sectionId as SectionId
|
|
: 'start';
|
|
const chapter = resolveChapterIntent(canonicalId);
|
|
const finiteIntensity = Number.isFinite(intensity) ? intensity : 0;
|
|
return Object.freeze({
|
|
atStart: sectionId === 'start',
|
|
intensity: Math.min(1, Math.max(0, finiteIntensity)),
|
|
bias: chapter.mood,
|
|
entryPhrase: chapter.entryPhrase,
|
|
});
|
|
}
|
|
|
|
export const DEFAULT_AUDIO_JOURNEY_STATE = resolveJourneyMusicState('start');
|