public async Task <IEnumerable <Trip> > SearchAsync(TripSearchRequest request) { // Search for offered trips var offeredTrips = tripOfferRepo.Query() .Where(t => request.Start.Equals(t.StartLocation)) .Where(t => request.End.Equals(t.EndLocation)) .Where(t => t.StartTime >= request.StartTime); // Search for trips provided by public transport var publicTrips = new List <Trip>(); foreach (var provider in publicTransportProviders) { try { var providerResult = await provider.SearchAsync(request); publicTrips.AddRange(providerResult); } catch (Exception ex) { logger.LogWarning(ex, "Provider '{0}' failed while searching for trips!", provider.GetType().Name); } } // Concat and order by duration return(offeredTrips .Concat(publicTrips) .OrderBy(t => t.StartTime) .ThenBy(t => t.EstimatedDuration)); }
public IEnumerable <KeyValuePair <string, string> > BuildSearch(TripSearchRequest request) { return(new Dictionary <string, string>() { { "existBikeEverywhere", "yes" }, { "existHafasAttrInc", "yes" }, { "existHafasDemo3", "yes" }, { "HWAI=JS!ajax", "yes" }, { "HWAI=JS!js", "yes" }, { "ignoreTypeCheck", "1" }, { "queryPageDisplayed", "yes" }, { "REQ0HafasSearchForw", "1" }, { "REQ0JourneyDate", request.StartTime.ToString("dd.MM.yyyy") }, { "REQ0JourneyProduct_list", "0:1111111111011100-000000" }, { "REQ0JourneyStopsS0A", "255" }, { "REQ0JourneyStopsS0G", request.Start.Name }, { "REQ0JourneyStopsS0ID", "" }, { "REQ0JourneyStopsZ0A", "255" }, { "REQ0JourneyStopsZ0G", request.End.Name }, { "REQ0JourneyStopsZ0ID", "" }, { "REQ0JourneyTime", request.StartTime.ToString("HH:mm") }, { "start", "Verbindungen suchen" }, { "wDayExt0", "Mo|Di|Mi|Do|Fr|Sa|So" }, { "wDayExt1", "Mo|Di|Mi|Do|Fr|Sa|So" } }); }
public Task <IEnumerable <PublicTransportTrip> > SearchAsync(TripSearchRequest request) { throw new NotImplementedException(); }
public async Task <IEnumerable <PublicTransportTrip> > SearchAsync(TripSearchRequest request) { var client = new HttpClient(); var startResponse = (await client.GetAsync(options.Host)) .EnsureSuccessStatusCode(); var startHtml = new HtmlDocument(); startHtml.LoadHtml(await startResponse.Content.ReadAsStringAsync()); var formNode = startHtml.DocumentNode.SelectSingleNode("//form[@id='HFSQuery']"); var formAction = formNode.Attributes["action"].Value; int queryId = int.Parse(queryIdRegex.Match(formAction).Groups["id"].Value); var requestContent = options.BuildSearch(request); var response = (await client.PostAsync( options.SearchURI(queryId), new FormUrlEncodedContent(requestContent))) .EnsureSuccessStatusCode(); var resultHtml = new HtmlDocument(); resultHtml.LoadHtml(await response.Content.ReadAsStringAsync()); var resultTable = resultHtml.DocumentNode.SelectSingleNode("//table[@class='resultTable']"); if (resultTable == null) { throw new InvalidOperationException("No trips could be found!"); } var result = new List <PublicTransportTrip>(); foreach (var row in resultTable.SelectNodes("//tr[starts-with(@id, 'trOverview') and not(starts-with(@id, 'trOverviewHint') )]")) { var builder = PublicTransportTrip.NewBuilder(Operator); DateTime startDate = DateTime.MinValue; TimeSpan startTime = TimeSpan.MinValue; DateTime endDate = DateTime.MinValue; TimeSpan endTime = TimeSpan.MinValue; foreach (var column in row.SelectNodes("td")) { switch (column.Attributes["headers"]?.Value) { case "hafasOVStop": var startStop = GetTextContent(column.FirstChild); var endStop = GetTextContent(column.LastChild); builder.SetStartLocation(new Destination(startStop, 0, 0)); builder.SetEndLocation(new Destination(endStop, 0, 0)); break; case "hafasOVDate": startDate = DateTime.ParseExact(column.InnerText, "dd.MM.yyyy", CultureInfo.InvariantCulture); endDate = startDate; // TODO Could go over 2 days break; case "hafasOVTime": var planned = column.SelectSingleNode("div/div[@class='planed']").InnerText; string[] lines = planned.Trim().Split('\n'); startTime = TimeSpan.Parse(lines[0].Replace("ab", "")); endTime = TimeSpan.Parse(lines[1].Replace("an", "")); break; case "hafasOVDuration": var duration = TimeSpan.Parse(column.InnerText); break; case "hafasOVChanges": break; case "hafasOVProducts": builder.AddType(PublicTransportType.Train); // TODO break; default: break; } } builder.SetStartTime(startDate + startTime); builder.SetEndTime(endDate + endTime); result.Add(builder.Build()); } return(result); string GetTextContent(HtmlNode node) { string text = node.InnerText; text = HtmlEntity.DeEntitize(text); return(text.Trim()); } }