/* Extract all lines and bounds affected by real time delays from list of delayed sections */ func extractAffectedLinesBoundsFromDelays(delays map[string]map[string]map[string]int64) map[string]map[string]bool { adjacentStops := make(map[string]map[string]bool) for fromStop, fromStopDetails := range delays { for toStop, _ := range fromStopDetails { _, exists := adjacentStops[fromStop] if !exists { adjacentStops[fromStop] = make(map[string]bool) } adjacentStops[fromStop][toStop] = true } } result := make(map[string]map[string]bool) lineBoundsServingAdjacentStops := selectdb.SelectLineBoundsServingMultipleAdjacentStops(adjacentStops) for _, fromStopDetails := range lineBoundsServingAdjacentStops { for _, toStopDetails := range fromStopDetails { for line, bound := range toStopDetails { _, exists := result[line] if !exists { result[line] = make(map[string]bool) } result[line][bound] = true } } } return result }
/* Returns affected lines (as slice) and line bound combinations (as map) for each pair of affected adjacent stops in delays */ func extractAllAffectedLineBounds(delays map[string]map[string]map[string]int64) (map[string]map[string][]string, map[string]map[string]map[string]string) { if len(delays) == 0 { return nil, nil } adjacentStops := make(map[string]map[string]bool) for fromStop, fromStopDetails := range delays { for toStop, _ := range fromStopDetails { _, exists := adjacentStops[fromStop] if !exists { adjacentStops[fromStop] = make(map[string]bool) } adjacentStops[fromStop][toStop] = true } } lineBoundMap := selectdb.SelectLineBoundsServingMultipleAdjacentStops(adjacentStops) linesMap := make(map[string]map[string][]string) for fromStop, fromStopDetails := range lineBoundMap { for toStop, toStopDetails := range fromStopDetails { for line, _ := range toStopDetails { _, exists := linesMap[fromStop] if !exists { linesMap[fromStop] = make(map[string][]string) } _, exists = linesMap[fromStop][toStop] if !exists { linesMap[fromStop][toStop] = make([]string, 0) } linesMap[fromStop][toStop] = append(linesMap[fromStop][toStop], line) } } } return linesMap, lineBoundMap }
/* Delay characteristics represented by map fromId => (toId => (day of week => (time of day => (delayThreshold => (numBuses => expected lasting time))))) */ func computeDelayCharacteristics(adjacentStops map[string]map[string]bool) map[string]map[string]map[int]map[int]map[time.Duration]map[int]time.Duration { delayCharacteristics := make(map[string]map[string]map[int]map[int]map[time.Duration]map[int]time.Duration) /* Channel for delay characteristics */ ch := make(chan map[string]map[string]map[int]map[int]map[time.Duration]map[int]time.Duration) lineBounds := selectdb.SelectLineBoundsServingMultipleAdjacentStops(adjacentStops) for fromStop, details := range adjacentStops { fromStopDelayCharacteristics := make(map[string]map[int]map[int]map[time.Duration]map[int]time.Duration) for toStop, _ := range details { go func(fromStop, toStop string) { /* Form time ranges - Compute for the weekday/weekend of yesterday */ timeRanges := make(map[time.Time]time.Time) endOfYesterday := time.Now().In(timezone.Get()).Truncate(24 * time.Hour) startOfYesterday := endOfYesterday.AddDate(0, 0, -1) weekday := startOfYesterday.Weekday() for _, day := range daysToLookBack { timeRanges[startOfYesterday.AddDate(0, 0, -day)] = endOfYesterday.AddDate(0, 0, -day) } /* Select journey history */ journeyHistory := selectdb.SelectJourneyHistory(fromStop, toStop, timeRanges, nil) times := make([]time.Time, len(journeyHistory)) actualDurations := make([]time.Duration, len(journeyHistory)) for i, record := range journeyHistory { times[i] = record.ToTimestamp actualDurations[i] = time.Duration(record.TimeTaken) * time.Second } /* Select historic journey times */ var line, bound string for k, v := range lineBounds[fromStop][toStop] { line = k bound = v } /* Generate times at intervals for prediction efficiency */ timesAtIntervals := make([]time.Time, 0) for startTime, endTime := range timeRanges { for t := startTime.Round(predictionInterval); t.Before(endTime.Add(predictionInterval)); t = t.Add(predictionInterval) { timesAtIntervals = append(timesAtIntervals, t) } } historicTimes := PredictJourneyTimes(line, bound, fromStop, toStop, timesAtIntervals, DefaultHistoric(), nil) historicDurations := make([]time.Duration, len(journeyHistory)) for i, t := range times { historicDurations[i] = historicTimes[t.Round(predictionInterval)] } delayCharacteristics := map[string]map[string]map[int]map[int]map[time.Duration]map[int]time.Duration{ fromStop: map[string]map[int]map[int]map[time.Duration]map[int]time.Duration{ toStop: computeDelayCharacteristicsForStopPair(fromStop, toStop, weekday, times, actualDurations, historicDurations), }, } updateDelayCharacteristics(delayCharacteristics) ch <- delayCharacteristics }(fromStop, toStop) fromStopDelayCharacteristics[toStop] = nil // fromStopDelayCharacteristics[toStop] = computeDelayCharacteristicsForStopPair(fromStop, toStop, times, actualDurations, historicDurations) } // delayCharacteristics[fromStop] = fromStopDelayCharacteristics delayCharacteristics[fromStop] = fromStopDelayCharacteristics } for _, v := range adjacentStops { for range v { <-ch /*entry := <-ch delayCharacteristics[entry.fromStop][entry.toStop] = entry.entry updateDelayCharacteristics(delayCharacteristics)*/ } } return delayCharacteristics }