module import _ from "lodash" ; interface Memo { i : number ; } export interface Event { time : number ; } export function sortEvents ( events ) { return events . sort ( ( a , b ) => a . time - b . time ) ; } export function clipTime ( events , start , end ) { return events . filter ( e => e . time >= start && e . time <= end ) ; } param { Array } events return { Function } export function eventListIterator ( events ) { const sorted = sortEvents ( events ) ; const length = sorted . length ; return ( now , memo ? ) : object | void => { if ( length === 0 ) { return ; } if ( memo ) { const event = sorted [ memo . i ] ; if ( event ) { return { event , memo : { i : memo . i + 1 } , } ; } } else { for ( let i = 0 ; i < length ; i += 1 ) { const event = sorted [ i ] ; const delta = event . time - now ; if ( delta >= 0 ) { return { event , memo : { i : i + 1 } , } ; } } } } ; } param { Array } events param { number } loopTime return { Function } export function loopedEventListIterator ( events , loopTime ) { const sorted = clipTime ( sortEvents ( events ) , 0 , loopTime ) ; const length = sorted . length ; return ( now , memo ? ) : object | void => { if ( length === 0 ) { return ; } if ( memo ) { const event = sorted [ memo . i % length ] ; const iteration = Math . floor ( memo . i / length ) ; const timeBase = iteration * loopTime ; if ( event ) { return { event : _ . assign ( { } , event , { time : timeBase + event . time } ) , memo : { i : memo . i + 1 } , } ; } } else { const iteration = Math . max ( Math . floor ( now / loopTime ) , 0 ) ; let timeBase = iteration * loopTime ; const lastEventTime = sorted [ length - 1 ] . time ; if ( now > timeBase + lastEventTime && now < timeBase + loopTime ) { timeBase = timeBase + loopTime ; } for ( let i = 0 ; i < length ; i += 1 ) { const event = sorted [ i ] ; const time = timeBase + event . time ; const delta = time - now ; if ( delta >= 0 ) { return { event : _ . assign ( { } , event , { time } ) , memo : { i : iteration * length + i + 1 } , } ; } } } } ; }