import EtudeError from "../error/EtudeError"; import Exceptional from "../util/Exceptional"; import MathUtil from "../util/MathUtil"; export default class Dynamic { public static MINIMUM_VELOCITY = 0; public static MAXIMUM_VELOCITY = 127; public static size = 0; private static _values = []; public static PIANISSISSIMO = new Dynamic(16); public static PIANISSIMO = new Dynamic(32); public static PIANO = new Dynamic(48); public static MEZZO_PIANO = new Dynamic(64); public static MEZZO_FORTE = new Dynamic(80); public static FORTE = new Dynamic(96); public static FORTISSIMO = new Dynamic(112); public static FORTISSISSIMO = new Dynamic(127); private constructor(private velocity: number) { ++Dynamic.size; Dynamic._values.push(this); this.velocity = MathUtil.clamp(Dynamic.MINIMUM_VELOCITY, Dynamic.MAXIMUM_VELOCITY, velocity); } public static values(): Dynamic[] { return Dynamic._values.slice(); } public ordinal(): number { return Dynamic._values.indexOf(this); } public static valueOf(dynamicString: string): Dynamic { const dynamic = Dynamic[dynamicString]; if (dynamic instanceof Dynamic) { return dynamic; } throw EtudeError.forInvalid(Dynamic, dynamicString); } public crescendo(amount: number): Dynamic { return new Dynamic(this.velocity + amount); } public diminuendo(amount: number): Dynamic { return new Dynamic(this.velocity - amount); } public static fromString(dynamicString: string): Exceptional { return Exceptional .ofNullable(dynamicString) .map(s => s.trim()) .filter(s => !s.isEmpty()) .flatMap(s => { let dynamic: Dynamic; switch(s){ case "ppp": dynamic = Dynamic.PIANISSISSIMO; break; case "pp": dynamic = Dynamic.PIANISSIMO; break; case "p": dynamic = Dynamic.PIANO; break; case "mp": dynamic = Dynamic.MEZZO_PIANO; break; case "mf": dynamic = Dynamic.MEZZO_FORTE; break; case "f": dynamic = Dynamic.FORTE; break; case "ff": dynamic = Dynamic.FORTISSIMO; break; case "fff": dynamic = Dynamic.FORTISSISSIMO; break; default: dynamic = null; } return Exceptional.ofNullable(dynamic); }); } public toString(): string { return this.velocity.toString(); } public getVelocity(): number { return this.velocity; } }