Light12306/TrainInfomationProviderService/TrainInfo/TrainInfoSearchProvider.cs
2015-12-07 02:30:22 +08:00

265 lines
7.0 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TrainInfomationProviderService.StationInfo;
using TrainInfomationProviderService.TrainInfo.Entities;
namespace TrainInfomationProviderService.TrainInfo
{
using Newtonsoft.Json;
public class TrainInfoSearchProvider
{
#region
static TrainInfoSearchProvider _instance;
static readonly object _lockObject = new object();
public static TrainInfoSearchProvider Instance
{
get
{
if (_instance == null)
{
lock (_lockObject)
{
if (_instance == null)
{
_instance = new TrainInfoSearchProvider();
}
}
}
return _instance;
}
}
#endregion
/// <summary>
/// 是否已就绪
/// </summary>
public bool IsReady { get; private set; }
public IndexStorage Storage { get; private set; }
public Dictionary<string, HashSet<string>> SameStationInfo { get; set; }
private TrainInfoSearchProvider()
{
}
public void Init()
{
Trace.TraceInformation("[TRAIN_INFO_SEARCH_PROVIDER] 正在创建车站-车次信息索引对象");
Storage = TrainInfoManager.Instance.IndexStorage;
Trace.TraceInformation("[TRAIN_INFO_SEARCH_PROVIDER] 完成创建车站-车次信息索引对象");
IsReady = true;
}
public List<TrainLineSegment> FindDirectTrains(ref DateTime date, string from, string to)
{
TrainInfoStorage infoStorage = null;
var minDate = DateTime.Now.Date;
while (date >= minDate)
{
infoStorage = Storage.TrainInfoStorages.GetValue(date.ToString("yyyy-MM-dd"));
if (infoStorage == null || infoStorage.Trains.Count == 0)
date = date.AddDays(-1);
else break;
}
var result = new List<TrainLineSegment>();
if (infoStorage == null)
return result;
for (var i = 0; i < infoStorage.Trains.Count; i++)
{
var train = infoStorage.Trains[i];
var stf = FindStop(train, from);
if (stf == null)
continue;
var stt = FindStop(train, to);
if (stt == null)
continue;
if (stf.Index >= stt.Index)
continue;
result.Add(new TrainLineSegment(train, stf, stt, date));
}
return result;
}
public TrainTransitOnceResultCollection FindOnceTransitTrains(DateTime date, string from, string to, TrainTransitSearchOptions options)
{
TrainInfoStorage infoStorage = null;
var minDate = DateTime.Now.Date;
while (date >= minDate)
{
infoStorage = Storage.TrainInfoStorages.GetValue(date.ToString("yyyy-MM-dd"));
if (infoStorage == null || infoStorage.Trains.Count == 0)
date = date.AddDays(-1);
else break;
}
if (infoStorage == null)
return null;
var result = new TrainTransitOnceResultCollection(date, options, from, to);
//发车经过车站
var fromStations = GetSameStations(from);
var toStations = GetSameStations(to);
var fromTrains = fromStations.Select(s => infoStorage.StationLeftTrainData.GetValue(s)).ExceptNull().SelectMany(s => s).ToHashSet();
var toTrains = toStations.Select(s => infoStorage.StationArriveTrainData.GetValue(s)).ExceptNull().SelectMany(s => s).ToHashSet();
//排除交集
var exclude = fromTrains.Intersect(toTrains).ToHashSet();
exclude.ForEach(s =>
{
fromTrains.Remove(s);
toTrains.Remove(s);
});
foreach (var fromTrain in fromTrains)
{
var startStop = FindStop(fromTrain, from);
//如果这车过终点站,则忽略
if (FindStop(fromTrain, to) != null)
{
continue;
}
foreach (var fstop in fromTrain.TrainStops.SkipWhile(x => startStop != x).Skip(1).Where(s => s != null && !string.IsNullOrEmpty(s.Code)))
{
foreach (var toTrain in toTrains)
{
//如果这车过发车站,则忽略
if (FindStop(toTrain, from) != null)
{
continue;
}
var toStop = FindStop(toTrain, to);
foreach (var tStop in toTrain.TrainStops.TakeWhile(x => toStop != x).Where(s => s != null && !string.IsNullOrEmpty(s.Code)))
{
try
{
if (fstop.Code == tStop.Code)
{
var firstTrain = new TrainLineSegment(fromTrain, startStop, fstop, date);
var secondTrain = new TrainLineSegment(toTrain, tStop, toStop, firstTrain.ArriveTime);
//一个中转点
var line = new TrainTransitOnceResult(
firstTrain,
secondTrain,
date
);
result.Add(line);
break;
}
if (IsStopInclude(fstop.Code, tStop.Code))
{
var firstTrain = new TrainLineSegment(fromTrain, startStop, fstop, date);
var secondTrain = new TrainLineSegment(toTrain, tStop, toStop, firstTrain.ArriveTime);
//一个中转点
var line = new TrainTransitOnceResult(
firstTrain,
secondTrain,
date,
true
);
result.Add(line);
break;
}
}
catch (Exception ex)
{
var msg = new StringBuilder(0x400);
msg.AppendLine("无法创建检测,错误信息:" + ex.ToString() + "\r\n\r\n相关数据\r\n=====================\r\n");
msg.Append("前车:");
msg.AppendLine(fromTrain == null ? "null" : JsonConvert.SerializeObject(fromTrain));
msg.Append("前车发站:");
msg.AppendLine(startStop == null ? "null" : JsonConvert.SerializeObject(startStop));
msg.Append("前车到站:");
msg.AppendLine(fstop == null ? "null" : JsonConvert.SerializeObject(fstop));
msg.Append("后车:");
msg.AppendLine(toTrain == null ? "null" : JsonConvert.SerializeObject(toTrain));
msg.Append("后车发站:");
msg.AppendLine(tStop == null ? "null" : JsonConvert.SerializeObject(tStop));
msg.Append("后车到站:");
msg.AppendLine(toStop == null ? "null" : JsonConvert.SerializeObject(toStop));
msg.Append("前车发站:");
msg.AppendLine(startStop == null ? "null" : JsonConvert.SerializeObject(startStop));
throw new Exception(msg.ToString(), ex);
}
}
}
}
}
result.SecondaryAnalyze();
return result;
}
HashSet<string> GetSameStations(string code)
{
var map = SameStationManager.SameStationMap;
if (map != null)
{
var hash = map.GetValue(code);
if (hash != null)
return hash;
}
return new HashSet<string>() { code };
}
bool IsStopInclude(string code1, string code2)
{
var map = SameStationManager.SameStationMap;
if (map == null)
return false;
var set = map.GetValue(code1);
return set != null && set.Contains(code2);
}
TrainStop FindStop(Train train, string code)
{
if (train == null || train.TrainStopMap == null)
return null;
var stop = train.TrainStopMap.GetValue(code);
if (stop != null)
return stop;
var map = SameStationManager.SameStationMap;
if (map == null)
return null;
var hash = map.GetValue(code);
if (hash == null)
return null;
foreach (var s in hash)
{
stop = train.TrainStopMap.GetValue(s);
if (stop != null)
return stop;
}
return null;
}
}
}