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); }
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); }