@@ -552,10 +552,43 @@ jQuery(document).ready(function () {
552552
553553 // hints for the current schedule
554554
555+ /** Find all pairs of overlapping intervals
556+ *
557+ * @param data Array of arbitrary interval-like objects with 'start' and 'end' properties
558+ * @returns Map from data item index to a list of overlapping data item indexes
559+ */
560+ function findOverlappingIntervals ( data ) {
561+ const overlaps = { } ; // results
562+ // Build ordered lists of start/end times, keeping track of the original index for each item
563+ const startIndexes = data . map ( ( d , i ) => ( { time : d . start , index : i } ) ) ;
564+ startIndexes . sort ( ( a , b ) => ( b . time - a . time ) ) ; // sort reversed
565+ const endIndexes = data . map ( ( d , i ) => ( { time : d . end , index : i } ) ) ;
566+ endIndexes . sort ( ( a , b ) => ( b . time - a . time ) ) ; // sort reversed
567+
568+ // items are sorted in reverse, so pop() will get the earliest item from each list
569+ let nextStart = startIndexes . pop ( ) ;
570+ let nextEnd = endIndexes . pop ( ) ;
571+ const openIntervalIndexes = [ ] ;
572+ while ( nextStart && nextEnd ) {
573+ if ( nextStart . time < nextEnd . time ) {
574+ // an interval opened - it overlaps all open intervals and all open intervals overlap it
575+ for ( const intervalIndex of openIntervalIndexes ) {
576+ overlaps [ intervalIndex ] . push ( nextStart . index ) ;
577+ }
578+ overlaps [ nextStart . index ] = [ ...openIntervalIndexes ] ; // make a copy of the open list
579+ openIntervalIndexes . push ( nextStart . index ) ;
580+ nextStart = startIndexes . pop ( ) ;
581+ } else {
582+ // an interval closed - remove its index from the list of open intervals
583+ openIntervalIndexes . splice ( openIntervalIndexes . indexOf ( nextEnd . index ) , 1 ) ;
584+ nextEnd = endIndexes . pop ( ) ;
585+ }
586+ }
587+ return overlaps ;
588+ }
589+
555590 function updateSessionConstraintViolations ( ) {
556- // do a sweep on sessions sorted by start time
557591 let scheduledSessions = [ ] ;
558-
559592 sessions . each ( function ( ) {
560593 let timeslot = jQuery ( this ) . closest ( ".timeslot" ) ;
561594 if ( timeslot . length === 1 ) {
@@ -569,19 +602,8 @@ jQuery(document).ready(function () {
569602 }
570603 } ) ;
571604
572- scheduledSessions . sort ( function ( a , b ) {
573- if ( a . start < b . start ) {
574- return - 1 ;
575- }
576- if ( a . start > b . start ) {
577- return 1 ;
578- }
579- return 0 ;
580- } ) ;
581-
582- let currentlyOpen = { } ;
583- let openedIndex = 0 ;
584- let markSessionConstraintViolations = function ( sess , currentlyOpen ) {
605+ // helper function to mark constraint violations
606+ const markSessionConstraintViolations = function ( sess , currentlyOpen ) {
585607 sess . element . find ( ".constraints > span" ) . each ( function ( ) {
586608 let sessionIds = this . dataset . sessions ;
587609
@@ -600,25 +622,15 @@ jQuery(document).ready(function () {
600622 } ) ;
601623 } ;
602624
603- for ( let i = 0 ; i < scheduledSessions . length ; ++ i ) {
604- let s = scheduledSessions [ i ] ;
605-
606- // prune
607- for ( let sessionIdStr in currentlyOpen ) {
608- if ( currentlyOpen [ sessionIdStr ] . end <= s . start ) {
609- delete currentlyOpen [ sessionIdStr ] ;
610- }
611- }
612-
613- // expand
614- while ( openedIndex < scheduledSessions . length && scheduledSessions [ openedIndex ] . start < s . end ) {
615- let toAdd = scheduledSessions [ openedIndex ] ;
616- currentlyOpen [ toAdd . id ] = toAdd ;
617- ++ openedIndex ;
625+ // now go through the sessions and mark constraint violations
626+ const overlaps = findOverlappingIntervals ( scheduledSessions ) ;
627+ for ( const index in overlaps ) {
628+ const currentlyOpen = { } ;
629+ for ( const overlapIndex of overlaps [ index ] ) {
630+ const otherSess = scheduledSessions [ overlapIndex ] ;
631+ currentlyOpen [ otherSess . id ] = otherSess ;
618632 }
619-
620- // check for violated constraints
621- markSessionConstraintViolations ( s , currentlyOpen ) ;
633+ markSessionConstraintViolations ( scheduledSessions [ index ] , currentlyOpen ) ;
622634 }
623635 }
624636
0 commit comments