private TimeSpan CalculateTimeCost(StationLineEntityExtender from, StationLineEntityExtender to, List <StationLineEntityExtender> stationLineListCache)
        {
            // Get 'to' previous station lines, and find the station which is the same as the 'from'
            List <StationLineEntityExtender> toPreviousStationLineList = new List <StationLineEntityExtender>();

            toPreviousStationLineList.Add(to);
            toPreviousStationLineList.AddRange(to.PreviousStationLineList.Select(sl => Convert(sl, stationLineListCache)).ToList());

            Stack <StationLineEntityExtender> fromFromToToStationLineStack = new Stack <StationLineEntityExtender>();

            foreach (StationLineEntityExtender toPreviousStationLine in toPreviousStationLineList)
            {
                if (toPreviousStationLine.Station != from.Station)
                {
                    fromFromToToStationLineStack.Push(toPreviousStationLine);
                }
                else
                {
                    fromFromToToStationLineStack.Push(toPreviousStationLine);
                    break;
                }
            }

            if (from.Station != fromFromToToStationLineStack.Peek().Station)
            {
                throw new Exception("From 'from' to 'to' is not in the same line");
            }

            // Calculate the time from 'from' to 'to'
            StationLineEntityExtender transferedLine = fromFromToToStationLineStack.Peek();
            bool     isTransfered     = (from != transferedLine);
            TimeSpan transferTimeCost = new TimeSpan();

            if (isTransfered)
            {
                List <MetroTransferEntity> toMetroTransferList = from.TransferToList;
                MetroTransferEntity        metroTransfer       = toMetroTransferList.Find(mt => Convert(mt.ToStationLine, stationLineListCache) == transferedLine);
                if (metroTransfer == null)
                {
                    throw new Exception("Cannot find the transfer data");
                }
                transferTimeCost = metroTransfer.TimeTransfer + new TimeSpan(transferedLine.TimeWait.Ticks / 2);
            }

            TimeSpan arrivedTimeCost = new TimeSpan();

            fromFromToToStationLineStack.Pop(); // no need to check the first line, if it is transfered, we have already calculated. if not, the arrive time is zero.
            while (fromFromToToStationLineStack.Count > 0)
            {
                StationLineEntity stationline = fromFromToToStationLineStack.Pop();
                arrivedTimeCost += stationline.TimeArrived;
            }

            return(transferTimeCost + arrivedTimeCost);
        }
Beispiel #2
0
        private List <MetroTransferEntity> SeachMetroTransferByFromStationLineIdQuery(int stationLineId)
        {
            List <MetroTransfer> matchedMetroTransferList =
                metroWeb.MetroWebDatabase.Table <MetroTransfer>().Select(new MetroTransfer {
                FromStationLineId = stationLineId
            });

            if (matchedMetroTransferList.Count == 0)
            {
                throw new Exception(string.Format("The from station line id {0} is not found.", stationLineId));
            }

            List <MetroTransferEntity> matchedMetroTransferEntityList = new List <MetroTransferEntity>();

            foreach (MetroTransfer matchedMetroTransfer in matchedMetroTransferList)
            {
                if (!metroTransferEntityList.Exists(metroTransfer => metroTransfer.TransferId == matchedMetroTransfer.TransferId))
                {
                    MetroTransferEntity matchedMetroTransferEntity = new MetroTransferEntity(metroWeb, matchedMetroTransfer);
                    matchedMetroTransferEntityList.Add(matchedMetroTransferEntity);
                }
            }
            return(matchedMetroTransferEntityList);
        }
        internal bool FullyGetRoute(StationEntity fromStation, List <StationLineEntityExtender> stationLineListCache, TimeSpan arrivedTimeLimit, Stack <StationLineEntityExtender> stationLineExtenderStatck)
        {
            // if current StationLine is the from staiton, return true
            if (this.Station == fromStation)
            {
                MinimumTime = new TimeSpan(TimeWait.Ticks / 2);
                MinimumRoute.Clear();
                MinimumRoute.Add(this);
                return(true);
            }

            // if current stationline is the end station, return false
            StationLineEntityExtender previousStationLineExtender = null;

            if (this.PreviousStationLine != null)
            {
                previousStationLineExtender = Convert(this.PreviousStationLine, stationLineListCache);
                if (stationLineExtenderStatck.Contains(previousStationLineExtender)) // avoid death loop
                {
                    previousStationLineExtender = null;
                }
            }

            List <StationLineEntityExtender> transferStationLineExtenderList = this.TransferFromList.Select(
                metroTransfer => Convert(metroTransfer.FromStationLine, stationLineListCache)).ToList(); // todo: this may return duplicate stationlines

            for (int i = transferStationLineExtenderList.Count - 1; i >= 0; i--)                         // avoid death loop
            {
                if (stationLineExtenderStatck.Contains(transferStationLineExtenderList[i]))
                {
                    transferStationLineExtenderList.RemoveAt(i);
                }
            }

            if (previousStationLineExtender == null && transferStationLineExtenderList.Count == 0)
            {
                return(false);
            }

            // if the previouStationLine is not the 'from' station, and the minmimum arrived time is greater than newArrivedTimeLimit, so we don't need to go further
            bool finalResult = false;

            if (previousStationLineExtender != null)
            {
                TimeSpan newArrivedTimeLimit           = arrivedTimeLimit - this.TimeArrived;
                TimeSpan previousStationLineArrivedMin = previousStationLineExtender.TimeArrived;

                foreach (MetroTransferEntity metroTransfer in previousStationLineExtender.TransferFromList)
                {
                    if (Convert(metroTransfer.ToStationLine, stationLineListCache) == previousStationLineExtender)
                    {
                        TimeSpan transferCost = metroTransfer.TimeTransfer + new TimeSpan(previousStationLineExtender.TimeWait.Ticks / 2);
                        previousStationLineArrivedMin = previousStationLineArrivedMin > transferCost ? transferCost : previousStationLineArrivedMin;
                    }
                }


                if (previousStationLineExtender.Station == fromStation || previousStationLineArrivedMin <= newArrivedTimeLimit)
                {
                    // get previous station FullyGetRoute
                    stationLineExtenderStatck.Push(this);
                    previousStationLineExtender.TransferTimes = this.TransferTimes;
                    bool found = previousStationLineExtender.FullyGetRoute(fromStation, stationLineListCache, newArrivedTimeLimit, stationLineExtenderStatck);
                    stationLineExtenderStatck.Pop();

                    if (found)
                    {
                        // compare whether current route is the minimum route
                        TimeSpan arriveTimeCost = previousStationLineExtender.MinimumTime + TimeArrived;
                        if (arriveTimeCost < MinimumTime)
                        {
                            MinimumTime  = arriveTimeCost;
                            MinimumRoute = new List <StationLineEntity>(previousStationLineExtender.MinimumRoute);
                            MinimumRoute.Add(this);
                        }
                        finalResult = true;
                    }
                }
            }

            // if we have already been transfered 4 times, we don't need to transfer any more because it is definitly not the nearest route
            if (TransferTimes < 5)
            {
                // if the transferStation is not the 'from' station, and the minmimum arrived time is greater than newArrivedTimeLimit, so we don't need to go further
                foreach (StationLineEntityExtender transferStationLine in transferStationLineExtenderList)
                {
                    List <MetroTransferEntity> toMetroTransferList = transferStationLine.TransferToList;
                    MetroTransferEntity        metroTransfer       = toMetroTransferList.Find(mt => Convert(mt.ToStationLine, stationLineListCache) == this);
                    if (metroTransfer == null)
                    {
                        throw new Exception("Cannot find the transfer data, something wrong?!");
                    }
                    TimeSpan transferTimeCost    = metroTransfer.TimeTransfer + new TimeSpan(this.TimeWait.Ticks / 2);
                    TimeSpan newArrivedTimeLimit = arrivedTimeLimit - transferTimeCost - transferStationLine.TimeArrived;

                    StationLineEntityExtender transferStationPreviousStationLine = Convert(transferStationLine.PreviousStationLine, stationLineListCache);
                    TimeSpan transferStationLineArrivedMin = transferStationPreviousStationLine.TimeArrived;

                    foreach (MetroTransferEntity transferMetroTransfer in transferStationPreviousStationLine.TransferFromList)
                    {
                        if (Convert(metroTransfer.ToStationLine, stationLineListCache) == transferStationLine)
                        {
                            TimeSpan transferCost = transferMetroTransfer.TimeTransfer + new TimeSpan(transferStationLine.TimeWait.Ticks / 2);
                            transferStationLineArrivedMin = transferStationLineArrivedMin > transferCost ? transferCost : transferStationLineArrivedMin;
                        }
                    }

                    if (transferStationPreviousStationLine.Station == fromStation || transferStationLineArrivedMin <= newArrivedTimeLimit)
                    {
                        // get transfer station
                        stationLineExtenderStatck.Push(this);
                        transferStationPreviousStationLine.TransferTimes = this.TransferTimes + 1;
                        bool found = transferStationPreviousStationLine.FullyGetRoute(fromStation, stationLineListCache, newArrivedTimeLimit, stationLineExtenderStatck);
                        stationLineExtenderStatck.Pop();

                        if (found)
                        {
                            // compare whether current route is the minimum route
                            TimeSpan arriveTimeCost = transferStationPreviousStationLine.MinimumTime + TimeArrived + transferTimeCost;
                            if (arriveTimeCost < MinimumTime)
                            {
                                MinimumTime  = arriveTimeCost;
                                MinimumRoute = new List <StationLineEntity>(transferStationPreviousStationLine.MinimumRoute);
                                MinimumRoute.Add(transferStationLine);
                            }
                            finalResult = true;
                        }
                    }
                }
            }

            return(finalResult);
        }