func predictJourneyWithHistoricData(intermediateStops map[string]map[string]bool, intermediateStopsOrdered []string,
	departureTime time.Time, dateRange []time.Time, options map[string]string) (map[string]map[string]map[string]int64, error) {
	if options["shifting"] == "true" {
		return selectdb.SelectAverageTimesTakenShifting(intermediateStopsOrdered, dateRange, departureTime, SlidingWindow, options)
	} else {
		return selectdb.SelectAverageTimesTaken(intermediateStops, dateRange, departureTime, SlidingWindow, options)
	}
}
/* Takes records up to 30 minutes before departure time, and looks for delay*/
func predictJourneyWithRealTimeData(intermediateStops map[string]map[string]bool,
	departureTime time.Time, options map[string]string,
	cache map[string]map[string]map[time.Time]map[string]int64) (map[string]map[string]map[string]int64, error) {

	slidingWindow := SlidingWindow

	// Override sliding window (if specified)
	if options["slidingwindow"] != "" {
		slidingWindowInMinutes, err := strconv.Atoi(options["slidingwindow"])
		if err != nil {
			logger.GetLogger().Panic(err)
		}
		slidingWindow = time.Duration(slidingWindowInMinutes) * time.Minute
	}
	halfSlidingWindow := slidingWindow / 2

	targetTime := departureTime.Add(-halfSlidingWindow)

	targetDate := []time.Time{
		targetTime,
	}

	results := make(map[string]map[string]map[string]int64)
	// intermediateStopsAbsentFromCache := make(map[string]map[string]bool)

	/* Check whether record exists in cache, if so use it directly to save connection to database */
	/*for fromStop, toStopDetails := range intermediateStops {
		for toStop, _ := range toStopDetails {
			// Search in cache for matching fromStop, toStop and departureTime
			cachedToStopDetails, cachedFromExists := cache[fromStop]
			if cachedFromExists {
				cachedDepartureTimeDetails, cachedToExists := cachedToStopDetails[toStop]
				if cachedToExists {
					cachedEstimates, cachedDepartureTimeExists := cachedDepartureTimeDetails[departureTime]
					if cachedDepartureTimeExists {
						results[fromStop] = map[string]map[string]int64{
							toStop: cachedEstimates,
						}
						continue
					}
				}
			}
			// Otherwise search failed, put to absent list
			intermediateStopsAbsentFromCache[fromStop] = map[string]bool{
				toStop: true,
			}
		}
	}

	if len(intermediateStopsAbsentFromCache) == 0 {
		logger.GetLogger().Info("Real time estimates (based on cache): %v", results)
		return results, nil
	}*/

	// For those absent, search in database and insert into results and cache
	var newResults map[string]map[string]map[string]int64
	var err error
	switch options["realtimemethod"] {
	case "mean":
		newResults, err = selectdb.SelectAverageTimesTaken(intermediateStops, targetDate, targetTime, slidingWindow, options)
	case "median":
		newResults, err = selectdb.SelectMedianTimesTaken( /*intermediateStopsAbsentFromCache*/ intermediateStops, targetDate, targetTime, slidingWindow, options)
	case "last":
		realTimeCount, err := strconv.Atoi(options["realtimecount"])
		if err != nil {
			logger.GetLogger().Panic(err)
		}
		newResults, err = selectdb.SelectLastFewTimesTaken(intermediateStops, targetDate, targetTime, slidingWindow, realTimeCount, options)
	default:
		logger.GetLogger().Panic("Unknown real time method")
	}

	for fromStop, toStopDetails := range newResults {
		for toStop, estimates := range toStopDetails {
			// Insert into results
			results[fromStop] = map[string]map[string]int64{
				toStop: estimates,
			}

			// Insert into cache
			/*cachedToStopDetails, cachedFromExists := cache[fromStop]
			if !cachedFromExists {
				cache[fromStop] = make(map[string]map[time.Time]map[string]int64)
			}
			_, cachedToExists := cachedToStopDetails[toStop]
			if !cachedToExists {
				cache[fromStop][toStop] = make(map[time.Time]map[string]int64)
			}
			cache[fromStop][toStop][departureTime] = estimates*/
		}
	}
	logger.GetLogger().Info("Real time estimates (straight from db): %v", results)
	return results, err
}