public static Dictionary<int, List<Fact>> NegativeAccelerationsBelowThreshold(Int16 carId, Int64 tripId, double threshold, double ignorableSpeed, TimeSpan ignorableTime, double ignorableDistance)
        {
            Dictionary<int, List<Fact>> negativeAccelerationsBelowThreshold = new Dictionary<int, List<Fact>>();
            int accelerationCount = 0;

            DBController dbc = new DBController();
            List<Fact> speedData = dbc.GetSpeedInformationByCarIdAndTripId(carId, tripId);
            dbc.Close();

            DateTime accelerationStartPoint = speedData[0].Temporal.Timestamp;
            double accelerationDistance = 0;
            bool belowThreshold = false;
            List<Fact> accelerationPoints = new List<Fact>();

            //For the entire trip
            foreach (Fact fact in speedData) {
                //If entry indicates acceleration below threshold, and above ignorable speeds
                if (fact.Measure.Speed > ignorableSpeed && fact.Measure.Acceleration < threshold) {
                    accelerationDistance += fact.Spatial.DistanceToLag;

                    //If not previously below threshold, remember the time where driver began accelerating
                    if (!belowThreshold) {
                        accelerationStartPoint = fact.Temporal.Timestamp;
                        accelerationPoints.Add(fact);
                        belowThreshold = true;
                    }

                    //If driver is not below threshold
                } else {
                    //If previously below threshold, add the facts result
                    if (belowThreshold) {
                        if (fact.Temporal.Timestamp - accelerationStartPoint >= ignorableTime && accelerationDistance > ignorableDistance) {
                            negativeAccelerationsBelowThreshold.Add(accelerationCount, accelerationPoints);
                            accelerationCount++;
                        }

                        accelerationPoints = new List<Fact>();
                        accelerationDistance = 0;
                        belowThreshold = false;
                    }
                }
            }

            //Handle case where last entry in trip is still speeding
            if (belowThreshold) {
                if (speedData[speedData.Count - 1].Temporal.Timestamp - accelerationStartPoint >= ignorableTime && accelerationDistance > ignorableDistance) {
                    negativeAccelerationsBelowThreshold.Add(accelerationCount, accelerationPoints);
                }
            }

            return negativeAccelerationsBelowThreshold;
        }
        public static double DistanceAbove(Int16 carId, Int64 tripId, double ignorableSpeed, TimeSpan ignorableTime, double ignorableDistance)
        {
            double distanceSped = 0;

            DBController dbc = new DBController();
            List<Fact> speedData = dbc.GetSpeedInformationByCarIdAndTripId(carId, tripId);
            dbc.Close();

            bool speeding = false;
            DateTime speedingStartPoint = speedData[0].Temporal.Timestamp;
            double speedingDistance = 0;

            //For the entire trip
            foreach (Fact fact in speedData) {
                //If entry indicates speeding
                if (fact.Measure.Speed > fact.Segment.MaxSpeed + ignorableSpeed) {
                    speedingDistance += fact.Spatial.DistanceToLag;

                    //If not previously speeding, remember the time where driver began speeding
                    if (!speeding) {
                        speedingStartPoint = fact.Temporal.Timestamp;
                        speeding = true;
                    }

                    //If driver is not speeding
                } else {
                    //If previously speeding, add the speeding-time to the total
                    if (speeding) {
                        if (fact.Temporal.Timestamp - speedingStartPoint >= ignorableTime && speedingDistance > ignorableDistance) {
                            distanceSped += speedingDistance;
                        }

                        speedingDistance = 0;
                        speeding = false;
                    }
                }
            }

            //Handle case where last entry in trip is still speeding
            if (speeding) {
                if (speedData[speedData.Count - 1].Temporal.Timestamp - speedingStartPoint >= ignorableTime && speedingDistance > ignorableDistance) {
                    distanceSped += speedingDistance;
                }
            }

                return distanceSped;
        }
        public static List<Fact> Accelerations(Int16 carId, Int64 tripId)
        {
            DBController dbc = new DBController();
            List<Fact> accelerationData = dbc.GetSpeedInformationByCarIdAndTripId(carId, tripId);
            dbc.Close();

            for (int i = 1; i < accelerationData.Count(); i++) {
                //Acceleration = Velocity change / Time
                double velocityChange = accelerationData[i].Measure.Speed - accelerationData[i - 1].Measure.Speed;
                TimeSpan time = accelerationData[i].Temporal.Timestamp - accelerationData[i - 1].Temporal.Timestamp;
                double acceleration = velocityChange / time.Seconds;

                accelerationData[i].Measure.Acceleration = acceleration;
            }

            return accelerationData;
        }
        public static double DistanceBelow(Int16 carId, Int64 tripId, double ignorableSpeed, TimeSpan ignorableTime, double ignorableDistance)
        {
            double totalDistanceBelow = 0;

            DBController dbc = new DBController();
            List<Fact> speedData = dbc.GetSpeedInformationByCarIdAndTripId(carId, tripId);
            dbc.Close();

            bool belowLimit = false;
            DateTime belowLimitStartPoint = speedData[0].Temporal.Timestamp;
            double distanceBelowLimit = 0;

            //For the entire trip
            foreach (Fact fact in speedData) {
                //If entry indicates not speeding
                if (fact.Measure.Speed <= fact.Segment.MaxSpeed + ignorableSpeed) {
                    distanceBelowLimit += fact.Spatial.DistanceToLag;

                    //If not previously below limit, remember the time where driver got below limit
                    if (!belowLimit) {
                        belowLimitStartPoint = fact.Temporal.Timestamp;
                        belowLimit = true;
                    }

                    //If driver is speeding
                } else {
                    //If previously below limit, add the time below limit to the total
                    if (belowLimit) {
                        if (fact.Temporal.Timestamp - belowLimitStartPoint >= ignorableTime && distanceBelowLimit > ignorableDistance) {
                            totalDistanceBelow += distanceBelowLimit;
                        }
                        distanceBelowLimit = 0;
                        belowLimit = false;
                    }
                }
            }

            //Handle case where last entry in trip is below limit
            if (belowLimit) {
                if (speedData[speedData.Count - 1].Temporal.Timestamp - belowLimitStartPoint >= ignorableTime && distanceBelowLimit > ignorableDistance) {
                    totalDistanceBelow += distanceBelowLimit;
                }
            }

            return totalDistanceBelow;
        }
        public static double PercentageTimeAboveInThreshold(Int16 carId, Int64 tripId, double lowerPercentage, double upperPercentage, double ignorableSpeed, TimeSpan ignorableTime, double ignorableDistance)
        {
            lowerPercentage += 100;
            upperPercentage += 100;
            TimeSpan totalTimeInThreshold = new TimeSpan(0, 0, 0);
            TimeSpan totalTimeOutsideThreshold = new TimeSpan(0, 0, 0);

            DBController dbc = new DBController();
            List<Fact> speedData = dbc.GetSpeedInformationByCarIdAndTripId(carId, tripId);
            dbc.Close();

            DateTime speedingStartPoint = speedData[0].Temporal.Timestamp;
            double speedingDistance = 0;
            TimeSpan timeInThreshold = new TimeSpan(0, 0, 0);
            TimeSpan timeOutsideThreshold = new TimeSpan(0, 0, 0);
            bool speeding = false;

            //For the entire trip
            for (int i = 1; i < speedData.Count; i++) {
                //If entry indicates speeding
                double percentageOfMaxSpeed = ((speedData[i].Measure.Speed - ignorableSpeed) / speedData[i].Segment.MaxSpeed) * 100;

                if (percentageOfMaxSpeed > 100) {
                    speedingDistance += speedData[i].Spatial.DistanceToLag;

                    if (percentageOfMaxSpeed >= lowerPercentage && percentageOfMaxSpeed <= upperPercentage) {
                        timeInThreshold += speedData[i].Temporal.SecondsToLag;
                    } else {
                        timeOutsideThreshold += speedData[i].Temporal.SecondsToLag;
                    }
                    //If not previously speeding, remember the time where driver began speeding
                    if (!speeding) {
                        speedingStartPoint = speedData[i].Temporal.Timestamp;
                        speeding = true;
                    }

                    //If driver is not speeding
                } else {
                    //If previously speeding, add the speeding-time to the total
                    if (speeding) {
                        if (speedData[i].Temporal.Timestamp - speedingStartPoint >= ignorableTime && speedingDistance > ignorableDistance) {
                            totalTimeInThreshold += timeInThreshold;
                            totalTimeOutsideThreshold += timeOutsideThreshold;
                        }
                        timeInThreshold = new TimeSpan(0, 0, 0);
                        timeOutsideThreshold = new TimeSpan(0, 0, 0);
                        speedingDistance = 0;
                        speeding = false;
                    }
                }
            }

            //Handle case where last entry in trip is still speeding
            if (speeding) {
                if (speedData[speedData.Count - 1].Temporal.Timestamp - speedingStartPoint >= ignorableTime && speedingDistance > ignorableDistance) {
                    totalTimeInThreshold += timeInThreshold;
                    totalTimeOutsideThreshold += timeOutsideThreshold;
                }
            }

            return totalTimeInThreshold.Ticks / (totalTimeInThreshold.Ticks + totalTimeOutsideThreshold.Ticks) * 100;
        }