/// <summary>
        /// read all files regarding to the mobility of the city in all time.
        /// </summary>
        /// <param name="roadNetwork"></param>the road network that use.
        /// <param name="roadMapFilename"></param>specifies the path to the map of mobility edge to the edge of road network.
        /// <param name="speedDirectory"></param>specifies the directory to all the speed information.
        /// <param name="pickDropPointsDirectory"></param>specifies the directory to the pickup and dropoff points.
        /// <returns></returns>
        public static ToTalMobility ReadMobility(RoadNetwork roadNetwork, string roadMapFilename, string speedFilename, string pickDropPointsFilename, string dayName)
        {
            Console.WriteLine("start to read the road map file.");
            StreamReader srMap = new StreamReader(roadMapFilename);
            Dictionary <int, List <int> > edgeRecords = new Dictionary <int, List <int> >();

            while (srMap.Peek() > 0)
            {
                string[] items = srMap.ReadLine().Split(new char[] { '\t' });
                if (Convert.ToInt32(items[1]) >= 0)
                {
                    if (!edgeRecords.ContainsKey(Convert.ToInt32(items[1])))
                    {
                        List <int> oriEdges = new List <int>();
                        oriEdges.Add(Convert.ToInt32(items[0]));
                        edgeRecords.Add(Convert.ToInt32(items[1]), oriEdges);
                    }
                    else
                    {
                        edgeRecords[Convert.ToInt32(items[1])].Add(Convert.ToInt32(items[0]));
                    }
                }
            }
            srMap.Close();

            Console.WriteLine("start to read the speed file.");


            Time[] timeStamps             = new Time[Time.NUMSLOTPERDAY];
            List <PickDropPoint>[] points = new List <PickDropPoint> [Time.NUMSLOTPERDAY];
            List <MobilityEdge>[]  edges  = new List <MobilityEdge> [Time.NUMSLOTPERDAY];
            for (int i = 0; i < Time.NUMSLOTPERDAY; i++)
            {
                points[i] = new List <PickDropPoint>();
                edges[i]  = new List <MobilityEdge>();
            }

            FileInfo     fRead       = new FileInfo(speedFilename);
            var          totalSize   = fRead.Length;
            var          fs          = fRead.OpenRead();
            StreamReader srSpeed     = new StreamReader(fs);
            long         completeOld = 0;

            StreamWriter swSpeed = new StreamWriter(@"D:\Result\Temporary\SpeedDistribution\speed.txt");

            int count = 0;

            while (srSpeed.Peek() > 0)
            {
                string[] items    = srSpeed.ReadLine().Split(new char[] { ' ' });
                int      edgeID   = Convert.ToInt32(items[0]);
                int      timeSlot = Convert.ToInt32(items[1]) / 2;
                if (Convert.ToInt32(items[1]) == 1)
                {
                    ;
                }
                double avgs        = Convert.ToDouble(items[2]);
                int    numVehicles = Convert.ToInt32(items[4]);
                if (numVehicles < 0)
                {
                    numVehicles = 0;
                }
                double stds  = Convert.ToDouble(items[3]);
                int    year  = Convert.ToInt32(dayName.Substring(0, 4));
                int    month = Convert.ToInt32(dayName.Substring(4, 2));
                int    day   = Convert.ToInt32(dayName.Substring(6, 2));

                swSpeed.WriteLine(avgs);

                timeStamps[timeSlot] = new Time(year, month, day, timeSlot);
                foreach (var ind in edgeRecords[edgeID])
                {
                    Edge oriEdge = roadNetwork.Edges[ind];
                    edges[timeSlot].Add(new MobilityEdge(oriEdge.EdgeID, oriEdge.StartID, oriEdge.EndID, oriEdge.Length, oriEdge.RoadClass,
                                                         oriEdge.Direction, oriEdge.FormWay, oriEdge.Urban, oriEdge.MaxLanes, oriEdge.MaxSpeed, oriEdge.Level,
                                                         oriEdge.AttributeNum, oriEdge.Points, avgs, numVehicles, stds));
                }

                long complete = fs.Position * 10 / totalSize;
                if (complete != completeOld)
                {
                    Console.WriteLine(complete * 10 + "% completed!");
                }
                completeOld = complete;
                count++;
            }
            srSpeed.Close();
            swSpeed.Close();

            Console.WriteLine("start to read the pickdroppoint directory.");
            StreamReader srPoint = new StreamReader(pickDropPointsFilename);

            while (srPoint.Peek() > 0)
            {
                string[] items = srPoint.ReadLine().Split(new char[] { ' ', ':', '/' });
                int      hour  = Convert.ToInt32(items[3]);
                int      min   = Convert.ToInt32(items[4]);
                //int timeSlot = (min <= 30) ? (hour * 2) : (hour * 2 + 1);
                int     timeSlot = hour;
                LatLong location = new LatLong(Convert.ToDouble(items[6]), Convert.ToDouble(items[7]));
                points[timeSlot].Add(new PickDropPoint(location, Convert.ToInt32(items[8])));
            }
            srPoint.Close();


            //start to built the totalModality
            Mobility[] mobilities = new Mobility[Time.NUMSLOTPERDAY];
            for (int i = 0; i < Time.NUMSLOTPERDAY; i++)
            {
                if (timeStamps[i] != null)
                {
                    mobilities[i] = new Mobility(edges[i], points[i], timeStamps[i]);
                }
            }
            ToTalMobility totalModality = new ToTalMobility(roadNetwork.Nodes, mobilities);

            return(totalModality);
        }
        public void TotalMobilityFeature(Grid grid, string mobilityFeatureDirectory)
        {
            int gridNum = grid.GridNumLat * grid.GridNumLon;

            DirectoryInfo dir = new DirectoryInfo(mobilityFeatureDirectory);

            for (int i = 0; i < this.NumTimeSlots; i++)
            {
                Mobility mobility = this.Mobilities[i];

                if (mobility != null)
                {
                    //figure out which edges are contained in each region
                    List <MobilityEdge>[] regionEdges = new List <MobilityEdge> [gridNum];
                    for (int j = 0; j < gridNum; j++)
                    {
                        regionEdges[j] = new List <MobilityEdge>();
                    }
                    foreach (var mobilityEdge in mobility.Edges)
                    {
                        List <int> indexRegion = new List <int>();
                        foreach (var latlong in mobilityEdge.Points)
                        {
                            int index = grid.RetrieveIndex(latlong);
                            if (!indexRegion.Contains(index))
                            {
                                indexRegion.Add(index);
                            }
                        }

                        foreach (var index in indexRegion)
                        {
                            regionEdges[index].Add(mobilityEdge);
                        }
                    }

                    //figure out which pickdroppoints are contained in each region
                    List <PickDropPoint>[] regionPoints = new List <PickDropPoint> [gridNum];
                    for (int j = 0; j < gridNum; j++)
                    {
                        regionPoints[j] = new List <PickDropPoint>();
                    }
                    foreach (var point in mobility.Points)
                    {
                        int index = grid.RetrieveIndex(point.Location);
                        if (index < gridNum && index >= 0)
                        {
                            regionPoints[index].Add(point);
                        }
                    }

                    //start to generate features
                    List <double>[] mobilityFeature = new List <double> [gridNum];
                    for (int j = 0; j < gridNum; j++)
                    {
                        mobilityFeature[j] = new List <double>();
                        //feature 1: expectation of the average speed regarding to road lengths in the region
                        double avgAvgSpeed = 0.0;
                        //feature 2: deviation of the average speed regarding to road lengths in the region
                        double stdAvgSpeed = 0.0;
                        //feature 3: expectation of the deviation speed regarding to road lengths in the region
                        double avgStdSpeed = 0.0;
                        //feature 4: deviation of the deviation speed regarding to road lengths in the region
                        double stdStdSpeed = 0.0;
                        //feature 5: number of vechicles that tranverse the region
                        int numVehicles = 0;
                        //feature 6: number of road segments with average speed in (0,6)
                        int numSpeedSix = 0;
                        //feature 7: number of road segments with average speed in (6-12)
                        int numSpeedTwelve = 0;
                        //feature 8: number of road segments with average speed in (12-18)
                        int numSpeedEighteen = 0;
                        //feature 9: number of road segments with average speed in (18-)
                        int numSpeedTop = 0;
                        //feature 12: number of road segments with average speed in (0,2)
                        int numSpeed1 = 0;
                        //feature 13: number of road segments with average speed in (2,4)
                        int numSpeed2 = 0;
                        //feature 14: number of road segments with average speed in (4,6)
                        int numSpeed3 = 0;
                        //feature 15: number of road segments with average speed in (6,8)
                        int numSpeed4 = 0;
                        //feature 16: number of road segments with average speed in (8,10)
                        int numSpeed5 = 0;
                        //feature 17: number of road segments with average speed in (10,12)
                        int numSpeed6 = 0;
                        //feature 18: number of road segments with average speed in (12,14)
                        int numSpeed7 = 0;
                        //feature 19: number of road segments with average speed in (14,16)
                        int numSpeed8 = 0;
                        //feature 20: number of road segments with average speed in (16,18)
                        int numSpeed9 = 0;
                        //feature 21: number of road segments with average speed in (18-)
                        int numSpeed10 = 0;

                        double totalLength = 0.0;
                        if (regionEdges[j].Count() > 0)
                        {
                            foreach (var edge in regionEdges[j])
                            {
                                if (edge.AverageSpeed < 6)
                                {
                                    numSpeedSix++;
                                }
                                else if (edge.AverageSpeed >= 6 && edge.AverageSpeed < 12)
                                {
                                    numSpeedTwelve++;
                                }
                                else if (edge.AverageSpeed >= 12 && edge.AverageSpeed < 18)
                                {
                                    numSpeedEighteen++;
                                }
                                else
                                {
                                    numSpeedTop++;
                                }

                                if (edge.AverageSpeed < 2)
                                {
                                    numSpeed1++;
                                }
                                else if (edge.AverageSpeed >= 2 && edge.AverageSpeed < 4)
                                {
                                    numSpeed2++;
                                }
                                else if (edge.AverageSpeed >= 4 && edge.AverageSpeed < 6)
                                {
                                    numSpeed3++;
                                }
                                else if (edge.AverageSpeed >= 6 && edge.AverageSpeed < 8)
                                {
                                    numSpeed4++;
                                }
                                else if (edge.AverageSpeed >= 8 && edge.AverageSpeed < 10)
                                {
                                    numSpeed5++;
                                }
                                else if (edge.AverageSpeed >= 10 && edge.AverageSpeed < 12)
                                {
                                    numSpeed6++;
                                }
                                else if (edge.AverageSpeed >= 12 && edge.AverageSpeed < 14)
                                {
                                    numSpeed7++;
                                }
                                else if (edge.AverageSpeed >= 14 && edge.AverageSpeed < 16)
                                {
                                    numSpeed8++;
                                }
                                else if (edge.AverageSpeed >= 16 && edge.AverageSpeed < 18)
                                {
                                    numSpeed9++;
                                }
                                else
                                {
                                    numSpeed10++;
                                }

                                avgAvgSpeed += edge.AverageSpeed; // *edge.Length;
                                avgStdSpeed += edge.StdSpeed;     //* edge.Length;
                                numVehicles += edge.NumVehicles;
                                totalLength += 1;                 // edge.Length;
                            }
                            avgAvgSpeed /= totalLength;
                            avgStdSpeed /= totalLength;
                            foreach (var edge in regionEdges[j])
                            {
                                stdAvgSpeed += Math.Pow((edge.AverageSpeed - avgAvgSpeed), 2); // *edge.Length;
                                stdStdSpeed += Math.Pow((edge.StdSpeed - avgStdSpeed), 2);     // *edge.Length;
                            }
                            stdAvgSpeed = Math.Sqrt(stdAvgSpeed / totalLength);
                            stdStdSpeed = Math.Sqrt(stdStdSpeed / totalLength);
                        }
                        mobilityFeature[j].Add(avgAvgSpeed);
                        mobilityFeature[j].Add(stdAvgSpeed);
                        mobilityFeature[j].Add(avgStdSpeed);
                        mobilityFeature[j].Add(stdStdSpeed);
                        mobilityFeature[j].Add(numVehicles);
                        mobilityFeature[j].Add(numSpeedSix);
                        mobilityFeature[j].Add(numSpeedTwelve);
                        mobilityFeature[j].Add(numSpeedEighteen);
                        mobilityFeature[j].Add(numSpeedTop);


                        //feature 10: number of pick up points in the region: meaning number of people outgoing
                        int pickup = 0;
                        //feature 11: number of drop off points in the region: meaning number of people ingoing
                        int dropoff = 0;

                        foreach (var point in regionPoints[j])
                        {
                            if (point.Flag == 1)
                            {
                                pickup++;
                            }
                            else
                            {
                                dropoff++;
                            }
                        }
                        mobilityFeature[j].Add(pickup);
                        mobilityFeature[j].Add(dropoff);

                        //mobilityFeature[j].Add(numSpeed1);
                        //mobilityFeature[j].Add(numSpeed2);
                        //mobilityFeature[j].Add(numSpeed3);
                        //mobilityFeature[j].Add(numSpeed4);
                        //mobilityFeature[j].Add(numSpeed5);
                        //mobilityFeature[j].Add(numSpeed6);
                        //mobilityFeature[j].Add(numSpeed7);
                        //mobilityFeature[j].Add(numSpeed8);
                        //mobilityFeature[j].Add(numSpeed9);
                        //mobilityFeature[j].Add(numSpeed10);
                    }

                    //start to output
                    string dirName = Path.Combine(dir.FullName, mobility.TimeStamp.Year.ToString() + mobility.TimeStamp.Month.ToString("D2") + mobility.TimeStamp.Day.ToString("D2"));
                    if (!Directory.Exists(dirName))
                    {
                        Directory.CreateDirectory(dirName);
                    }

                    string path = Path.Combine(dir.FullName, Path.Combine(dirName, mobility.TimeStamp.TimeSlot.ToString("D2")));
                    IO.WriteFeature(mobilityFeature, path);
                }
            }
        }