/**
 * Task that can be added to the [[TaskQueue]]
 */ export interface Task { /**
     * The Function that will be executed when the [[Task]] is processed
     */ execute : ( ) => void ; /**
     * The group by which similar tasks in the TaskQueue are combined
     */ group : string ; /**
     * A function to retrieve the priority of the [[Task]], with 0 being
     * the highest priority, and the first to be executed
     */ getPriority : ( ) => number ; /**
     * An optional function that defines if a [[Task]] is alread expired
     * and therefore can be removed from the [[TaskQueue]]
     */ isExpired ? : ( ) => boolean ; /**
     * An optional function that returns an estimated process time,
     * this is not directly used by the [[TaskQueue]] but can be used
     * by an Task Scheduler to schedule the processing
     */ estimatedProcessTime ? : ( ) => number ; } export interface TaskQueueOptions { /**
     * Groups to combine specific [[Task]]s in the [[TaskQueue]],
     * [[Task]]s can only be added to the [[TaskQueue]] if their group is available
     */ groups : string [ ] ; remarks Caution, the  TaskQueue uses the last element in the Arrays first, so the
     * highest priorities should be ordered to the end
      prioSortFn ? : ( a : Task , b : Task ) => number ; } /**
 * A Pull-TaskQueue sorted by priority and group-able  Task s by  Task . group .
 *
 *  remarks example export class TaskQueue { private readonly m_taskLists : Map < string , Task [ ] > = new Map ( ) ; constructor ( private readonly m_options ) { this . m_options . groups ?. forEach ( group => { this . m_taskLists . set ( group , [ ] ) ; } ) ; if ( this . m_options . prioSortFn ) { this . sort = this . m_options . prioSortFn ; } } param group update ( group ? ) { if ( group === undefined ) { this . m_taskLists . forEach ( taskList => { this . updateTaskList ( taskList ) ; } ) ; } else { const taskList = this . getTaskList ( group ) ; if ( taskList ) { this . updateTaskList ( taskList ) ; } } } param task returns add ( task ) { if ( this . m_taskLists . has ( task . group ) ) { const taskList = this . m_taskLists . get ( task . group ) ; if ( ! taskList ?. includes ( task ) ) { this . m_taskLists . get ( task . group ) ?. push ( task ) ; return true ; } } return false ; } param task returns remove ( task ) { if ( this . m_taskLists . has ( task . group ) ) { const index = this . m_taskLists . get ( task . group ) ?. indexOf ( task ) ; if ( index !== - 1 ) { this . m_taskLists . get ( task . group ) ?. splice ( index as number , 1 ) ; return true ; } } return false ; } param group numItemsLeft ( group ? ) { let numLeft = 0 ; if ( group === undefined ) { this . m_taskLists . forEach ( tasklist => { numLeft += tasklist . length ; } ) ; } else { numLeft += this . getTaskList ( group ) ?. length ?? 0 ; } return numLeft ; } param group param shouldProcess param n defaults returns processNext ( group , shouldProcess ? , n = 1 ) { if ( ! this . getTaskList ( group ) || this . numItemsLeft ( group ) <= 0 ) { return false ; } for ( let i = 0 ; i < n && this . numItemsLeft ( group ) > 0 ; i ++ ) { const nextTask = this . pull ( group , true ) ; if ( nextTask !== undefined ) { if ( ! shouldProcess || shouldProcess ?. ( nextTask ) ) { nextTask . execute ( ) ; } else { this . add ( nextTask ) ; } } } return true ; } clear ( ) { this . m_taskLists . clear ( ) ; } private pull ( group , checkIfExpired = false ) { const taskList = this . getTaskList ( group ) ; let nextTask ; if ( taskList ) { nextTask = this . getTaskList ( group ) ?. pop ( ) ; if ( checkIfExpired && nextTask && nextTask . isExpired ?. ( ) ) { return this . pull ( group , checkIfExpired ) ; } } return nextTask ; } private sort ( a , b ) { return b . getPriority ( ) - a . getPriority ( ) ; } private getTaskList ( group ) { return this . m_taskLists . get ( group ) ; } private updateTaskList ( taskList ) { for ( let i = 0 ; i < taskList . length ; i ++ ) { const task = taskList [ i ] ; if ( task ?. isExpired ?. ( ) ) { taskList . splice ( i , 1 ) ; i -- ; } } taskList . sort ( this . sort ) ; } }