export interface Tick { current: number, next?: { timestamp: number, events: TimestampEvent[] }, nextShot?: { timestamp: number, count: number } } export interface Config { availableTimelines: string[] } export interface Room { id: number, userCount: number, isLeader: boolean, running: boolean, startTime: number, seekTime: number, timelineName: string, readyToParticipate: boolean, speedFactor: number } export class RoomOptions { seekTime: number timelineName: string constructor(seekTime: number, timelineName: string) { this.seekTime = seekTime; this.timelineName = timelineName; } } export class Timeline { name: string songFile: string feed: TimelineItem[] constructor(obj: any) { this.name = obj.name; this.songFile = obj.songFile; this.feed = obj.feed; } itemAtTime(time: number, type: string = ''): [TimelineItem | null, TimelineItem | null] { let feedToSearch = type ? this.feed.filter(i => i.events.some(j => j.type == type)) : this.feed; for (let i = 1; i < feedToSearch.length; i++) { if (feedToSearch[i].timestamp * 1000 >= time) { return [feedToSearch[i - 1], feedToSearch[i]]; } } return [feedToSearch[feedToSearch.length - 1], null]; } eventAtTime(time: number, type: string = ''): [TimestampEvent | null, TimestampEvent | null] { let [current, next] = this.itemAtTime(time, type) return [current ? (current.events.find(i => i.type == type) || null) : null, next ? (next.events.find(i => i.type == type) || null) : null] } } export interface TimelineItem { timestamp: number, events: TimestampEvent[] } export interface TimestampEvent { type: 'talk' | 'shot' | 'song' | 'time', text: string[], shotCount?: number }