func getRoutePaths(linesToPlot map[string]map[string]map[string]string) map[string][]LatLng { routePaths := make(map[string][]LatLng) bound := "outbound" for line, lineDetails := range linesToPlot { fromStop := lineDetails[bound]["fromStop"] toStop := lineDetails[bound]["toStop"] intermediateStops := selectdb.SelectIntermediateStops(line, bound, fromStop, toStop) path := make([]LatLng, len(intermediateStops)) intermediateStopDetails := selectdb.SelectMultipleStops(intermediateStops) for i, stop := range intermediateStops { lat, err := strconv.ParseFloat(intermediateStopDetails[stop]["latitude"], 64) if err != nil { logger.GetLogger().Panic(err) } lng, err := strconv.ParseFloat(intermediateStopDetails[stop]["longitude"], 64) if err != nil { logger.GetLogger().Panic(err) } path[i] = LatLng{ Lat: lat, Lng: lng, } } routePaths[line] = path } return routePaths }
func getIcsCodes(lineBoundsStops map[string]map[string]string) map[string]map[string]string { stopsMap := make(map[string]bool) for _, lineDetails := range lineBoundsStops { for _, naptanId := range lineDetails { stopsMap[naptanId] = true } } stops := make([]string, len(stopsMap)) counter := 0 for stop, _ := range stopsMap { stops[counter] = stop counter++ } stopInfos := selectdb.SelectMultipleStops(stops) icsCodes := make(map[string]map[string]string) for line, lineDetails := range lineBoundsStops { for bound, naptanId := range lineDetails { _, exists := icsCodes[line] if !exists { icsCodes[line] = make(map[string]string) } icsCodes[line][bound] = stopInfos[naptanId]["icscode"] } } return icsCodes }
func getStopInfos(lineStopPointsByRoute map[string]map[string][]string) map[string]map[string][]TflStopPoint { /* Get slice of all stops */ stopsMap := make(map[string]bool) for _, lineDetails := range lineStopPointsByRoute { for _, orderedStopPoints := range lineDetails { for _, stop := range orderedStopPoints { stopsMap[stop] = true } } } stops := make([]string, len(stopsMap)) counter := 0 for stop, _ := range stopsMap { stops[counter] = stop counter++ } stopInfos := selectdb.SelectMultipleStops(stops) result := make(map[string]map[string][]TflStopPoint) for line, lineDetails := range lineStopPointsByRoute { for bound, orderedStopPoints := range lineDetails { for _, naptanId := range orderedStopPoints { _, exists := result[line] if !exists { result[line] = make(map[string][]TflStopPoint) } _, exists = result[line][bound] if !exists { result[line][bound] = make([]TflStopPoint, 0) } stopInfo := stopInfos[naptanId] name := stopInfo["name"] latitude, err := strconv.ParseFloat(stopInfo["latitude"], 64) if err != nil { logger.GetLogger().Panic(err) } longitude, err := strconv.ParseFloat(stopInfo["longitude"], 64) if err != nil { logger.GetLogger().Panic(err) } result[line][bound] = append(result[line][bound], TflStopPoint{ Name: name, NaptanId: naptanId, Latitude: latitude, Longitude: longitude, }) } } } return result }
/* Returns map from naptan ids to latitudes and longitudes map (naptanId => ("latitude" => latitude "longitude" => longitude )) */ func getLatLngs(naptanIds []string) map[string]map[string]float64 { stops := selectdb.SelectMultipleStops(naptanIds) result := make(map[string]map[string]float64) for _, stop := range stops { naptanId := stop["id"] latitude, err := strconv.ParseFloat(stop["latitude"], 64) if err != nil { logger.GetLogger().Panic(err) } longitude, err := strconv.ParseFloat(stop["longitude"], 64) if err != nil { logger.GetLogger().Panic(err) } result[naptanId] = map[string]float64{ "latitude": latitude, "longitude": longitude, } } return result }
/* Returns the stop details for each delayed section map (naptanId => ("name" => name "latitude" => lat "longitude" => lng ...))) */ func extractAllStopDetailsFromDelays(delays map[string]map[string]map[string]int64) map[string]map[string]string { if len(delays) == 0 { return nil } stopsMap := make(map[string]bool) for fromStop, fromStopDetails := range delays { for toStop, _ := range fromStopDetails { stopsMap[fromStop] = true stopsMap[toStop] = true } } stops := make([]string, len(stopsMap)) counter := 0 for stop, _ := range stopsMap { stops[counter] = stop counter++ } return selectdb.SelectMultipleStops(stops) }
/* Change the predictions inside directions to use our own predictions */ func (directions *TflDirections) UpdatePredictions(isDeparting bool, departureOrArrivalTime time.Time) error { journeys := &directions.Journeys for i := 0; i < len(*journeys); i++ { /* Counter for keeping track of times for prediction */ cumulativeTime := departureOrArrivalTime if !isDeparting { /* Approximate departure time for arriving case by subtracting tfl estimate */ cumulativeTime = departureOrArrivalTime.Add(-time.Duration((*journeys)[i].TflDuration) * time.Minute) } initialTime := cumulativeTime legs := &(*journeys)[i].Legs for j := 0; j < len(*legs); j++ { leg := &(*legs)[j] leg.DepartureTime = formatISOTime(cumulativeTime) if leg.Mode.Id == "bus" { var line string var bound string var stopPoints []string lineBoundCombination := make(map[string]string) /* Update naptan ids and coordinates of intermediate stops */ for i, routeOption := range leg.RouteOptions { var err error line = routeOption.LineIdentifier.Id stopPoints, bound, err = searchIntermediateStops(line, leg.DeparturePoint.IcsCode, leg.ArrivalPoint.IcsCode) if err != nil { /* Bus may not be Tfl operated (e.g. bus 555 to Heathrow). In such case skip. */ continue } /* Add bound to struct */ leg.RouteOptions[i].LineIdentifier.Bound = bound lineBoundCombination[line] = bound } /* If no stop points found, invalidate journey for removal afterwards*/ if len(stopPoints) == 0 { (*journeys)[i].IsInvalid = true continue } leg.IntermediateStops = make([]TflStopPoint, len(stopPoints)) details := selectdb.SelectMultipleStops(stopPoints) for i, naptanId := range stopPoints { latitude, _ := strconv.ParseFloat(details[naptanId]["latitude"], 64) longitude, _ := strconv.ParseFloat(details[naptanId]["longitude"], 64) leg.IntermediateStops[i] = TflStopPoint{ Name: details[naptanId]["name"], NaptanId: naptanId, Latitude: latitude, Longitude: longitude, } } /* Update bus prediction */ newPrediction, historicBasedPrediction, realTimeBasedPrediction, newPredictionAdjacentStops, err := updateBusPrediction(line, bound, stopPoints, cumulativeTime) if err == nil { leg.DurationInMinutes = int(newPrediction.Minutes()) leg.HistoricDurationInMinutes = int(historicBasedPrediction.Minutes()) leg.RealTimeDurationInMinutes = int(realTimeBasedPrediction.Minutes()) } /* Update next bus arrivals */ fromStop := leg.IntermediateStops[0].NaptanId nextBuses := selectdb.SelectNextBuses(lineBoundCombination, fromStop, time.Now().In(timezone.Get())) leg.NextBuses = make([]TflNextBus, len(nextBuses)) for i, nextBus := range nextBuses { leg.NextBuses[i] = TflNextBus{ Line: nextBus.Line, Bound: nextBus.Bound, VehicleId: nextBus.VehicleId, ExpectedArrivalTime: formatISOTime(nextBus.ExpectedArrivalTime), AlreadyDeparted: nextBus.AlreadyDeparted, } } addToNextBusesCurrentLocations(&leg.NextBuses) /* Find out next bus frequency */ averageWaitTime, minWaitTime, maxWaitTime, err := selectdb.SelectAverageWaitTimes(lineBoundCombination, initialTime) if err != nil { logger.GetLogger().Error(err.Error()) } leg.FrequencyLow = int(minWaitTime.Minutes()) leg.FrequencyHigh = int(maxWaitTime.Minutes()) nextBusFlag := false if len(nextBuses) > 0 { /* Find first bus that is going to arrive and the user is able to catch */ for _, nextBus := range nextBuses { nextBusTime := nextBus.ExpectedArrivalTime if nextBusTime.After(cumulativeTime) { leg.TimeToNextBus = int(nextBusTime.Sub(cumulativeTime).Minutes()) cumulativeTime = nextBusTime nextBusFlag = true break } } } if len(nextBuses) == 0 || (len(nextBuses) > 0 && !nextBusFlag) { /* Handle special case if lack of next buses, use average wait times instead */ leg.TimeToNextBus = int(averageWaitTime.Minutes()) cumulativeTime = cumulativeTime.Add(averageWaitTime) } /* Update cumulative time */ leg.IntermediateStops[0].ExpectedArrival = int(cumulativeTime.Sub(initialTime).Minutes()) for i := 0; i < len(stopPoints)-1; i++ { fromStop := stopPoints[i] toStop := stopPoints[i+1] cumulativeTime = cumulativeTime.Add(newPredictionAdjacentStops[fromStop][toStop]) leg.IntermediateStops[i+1].ExpectedArrival = int(cumulativeTime.Sub(initialTime).Minutes()) } } else { cumulativeTime = cumulativeTime.Add(time.Duration(leg.DurationInMinutes) * time.Minute) } } } /* Remove invalid journeys */ for i := len(*journeys) - 1; i >= 0; i-- { if (*journeys)[i].IsInvalid { *journeys = append((*journeys)[:i], (*journeys)[i+1:]...) } } return nil }