/// <summary> /// Parses the map.getData({ ... }) like looking javascript from the attribute /// </summary> /// <param name="origin">API response that was processed to make this statement</param> /// <param name="script">JavaScript to parse</param> /// <returns>StationIdentification statement or null if parsing fails</returns> public static StationIdStatement?FromScript(APIResponse origin, string?script) { if (script == null) { return(null); } var mapGetData = script.Split(new char[] { ';' }, 2)[0]; try { var data = JObject.Parse(mapGetData.Substr(mapGetData.IndexOf("{"), mapGetData.LastIndexOf("}"))); var id = CSExtensions.ParseInt(data["i"]?.ToString()); var stationName = data["a"]?.ToString(); if (stationName == null) { return(null); } return(new StationIdStatement(origin, stationName, id)); } catch (JsonReaderException) { return(null); } }
public MessageClientBase(Guid id, HttpRequest request, HttpResponse response, CancellationToken cancellationToken) { this.response = response; this.cancellationToken = cancellationToken; Id = id; LastMessageId = request.Headers.ContainsKey("Last-Event-ID") ? CSExtensions.ParseInt(request.Headers["Last-Event-ID"]) : null; response.ContentType = "text/event-stream"; }
/// <summary> /// Processes the station rows in the HTML response /// </summary> /// <param name="response">API response</param> /// <param name="row">Station row tr</param> /// <param name="number">Number of the train station (ordinal)</param> /// <param name="id">Identifies the train</param> /// <param name="lastStation">Last station (to link sequential stations together)</param> /// <returns>Parser statements</returns> private static List <ParserStatement> ProcessStationTableRow(APIResponse response, HtmlNode row, TrainIdStatement id, ref StationIdStatement?lastStation) { List <ParserStatement> ret = new List <ParserStatement>(); var tds = row.ChildNodes.Where(n => n.Name == "td").ToArray(); var stationLink = tds[1].Descendants("a").FirstOrDefault(); var stationId = StationIdStatement.FromScript(response, stationLink?.Attributes["onclick"]?.Value); if (stationId != null) { ret.Add(stationId); } else { ret.Add(new ErrorStatement(response, ErrorTypes.StationLinkUnparsable)); ret.Add(stationId = new StationIdStatement(response, stationLink?.InnerText.Trim(), null)); } var hit = row.HasClass("row_past_odd") || row.HasClass("row_past_even"); var distance = CSExtensions.ParseInt(tds[0].InnerText); var arrival = TimeTuple.Parse(tds[2]); var departure = TimeTuple.Parse(tds[3]); var platform = (tds.Length > 4) ? tds[4].InnerText.Trim() : null; if (platform?.Length == 0) { platform = null; } var trainStationId = new TrainStationStatement(response, id, stationId, arrival, departure); ret.Add(trainStationId); if (lastStation != null) { ret.Add(new TrainStationLinkStatement(response, id, lastStation, stationId, true)); } lastStation = stationId; ret.Add(new TrainStationDistanceStatement(response, trainStationId, distance)); ret.Add(new TrainStationPlatformStatement(response, trainStationId, platform)); ret.Add(new TrainStationHitStatement(response, trainStationId, hit)); return(ret); }
public static IEnumerable <ParserStatement> ParseTrainReference(APIResponse response, HtmlNode trainReference, StationIdStatement station, TimeSpan?arrival, TimeSpan?departure) { var enumerator = trainReference.ChildNodes.AsEnumerable().GetEnumerator(); TrainIdStatement id; if (enumerator.MoveNext()) { if (enumerator.Current.Name == "a") { var trainNumber = CSExtensions.ParseInt(enumerator.Current.InnerText); var elviraId = ElviraIdFromScript(enumerator.Current.Attributes["onclick"]?.Value); if (trainNumber != null) { yield return(id = new TrainIdStatement(response, trainNumber.Value, elviraId)); } else { yield return(new ErrorStatement(response, ErrorTypes.TrainReferenceUnparsable)); yield break; } } else { yield return(new ErrorStatement(response, ErrorTypes.TrainReferenceUnparsable)); yield break; } } else { yield return(new ErrorStatement(response, ErrorTypes.TrainReferenceUnparsable)); yield break; } if (enumerator.MoveNext()) { var textSplit = enumerator.Current.InnerText.Split(new char[0], StringSplitOptions.RemoveEmptyEntries); string? name = null; TrainType?type = null; foreach (var part in textSplit) { if ((type = TrainParser.DetermineTrainType(part)) != null) { break; } else { if (name == null) { name = part; } else { name += " " + part; } } } if (name != null) { yield return(new TrainNameStatement(response, id, name)); } if (type != null) { yield return(new TrainTypeStatement(response, id, type.Value)); } else { throw new Exception("Type does not map!"); } } else { yield break; } if (!enumerator.MoveNext()) { yield break; } if (enumerator.MoveNext()) { var text = enumerator.Current.InnerText; var parts = text.Split(" -- "); parts[0] = parts[0].Trim(); parts[1] = parts[1].Trim(); if (parts[0] == "" && parts[1] == "") { yield return(new ErrorStatement(response, ErrorTypes.TrainRelationUnparsable)); yield break; } var p0 = parts[0].Split(new char[0], StringSplitOptions.RemoveEmptyEntries); var p1 = parts[1].Split(new char[0], StringSplitOptions.RemoveEmptyEntries); if (parts[0] != "") { departure = null; } if (parts[1] != "") { arrival = null; } if (departure == null && TimeSpan.TryParse(p0[0].Trim(), out TimeSpan fromTime)) { departure = fromTime; } if (arrival == null && TimeSpan.TryParse(p1[1].Trim(), out TimeSpan toTime)) { arrival = toTime; } var from = parts[0] != "" ? new StationIdStatement(response, p0[1].Trim(), null) : station; var to = parts[1] != "" ? new StationIdStatement(response, p1[0].Trim(), null) : station; yield return(new TrainRelationStatement(response, id, from, to, departure, arrival)); } }
/// <summary> /// Parses an API response from the TRAIN API /// </summary> /// <param name="response">API response to parse</param> /// <returns>IEnumerable of ParserStatements</returns> public static IEnumerable <ParserStatement> Parse(APIResponse response) { if (!response.RequestSucceded) { yield return(new ErrorStatement(response, ErrorTypes.RequestUnsuccessful)); yield break; } int? trainNumber = null; string? elviraId = null; TrainIdStatement?id = null; if (response.Param?["vsz"] != null) { trainNumber = CSExtensions.ParseInt(response.Param["vsz"].ToString().Substring(2)); } if (response.Param?["v"] != null) { elviraId = response.Param["v"].ToString(); } if (trainNumber != null) { yield return(id = new TrainIdStatement(response, trainNumber.Value, elviraId)); } if (response.Result?["html"] != null) { HtmlDocument document = new HtmlDocument(); document.LoadHtml(HttpUtility.HtmlDecode(response.Result?["html"].ToString())); var table = document.DocumentNode.Descendants("table").Where(d => d.HasClass("vt")).FirstOrDefault()?.ChildNodes.Where(n => n.Name == "tbody").FirstOrDefault(); if (table != null) { foreach (ParserStatement statement in ProcessHeader(response, table, ref id, elviraId)) { yield return(statement); } if (id != null) { var expiryDateLink = document.DocumentNode.FirstChild.ChildNodes.SkipWhile(h => h.InnerText.Trim() != "Menetrend").SkipWhile(ul => ul.Name != "ul").FirstOrDefault()?.Descendants("li") .FirstOrDefault(li => li.Attributes.Contains("style") && li.Attributes["style"].Value.Contains("bolder")) ?.Descendants("a").FirstOrDefault(); yield return(new TrainExpiryStatement(response, id, expiryDateLink == null ? (DateTime?)null : DateTime.Parse(expiryDateLink.InnerText.Split('-')[1]))); StationIdStatement?lastStation = null; foreach (HtmlNode tr in table.ChildNodes.Where(n => n.Name == "tr" && n.Attributes["onmouseover"] != null && n.Attributes["onmouseout"] != null)) { foreach (ParserStatement statement in ProcessStationTableRow(response, tr, id, ref lastStation)) { yield return(statement); } } } } else { yield return(new ErrorStatement(response, ErrorTypes.NoTable)); } } else { yield return(new ErrorStatement(response, ErrorTypes.NoResult)); } if (id != null && response.Result?["line"][0]["points"] != null) { yield return(new TrainPolylineStatement(response, id, response.Result?["line"][0]["points"]?.ToString())); } }
/// <summary> /// Processes the train header part of the HTML response /// </summary> /// <param name="response">API response</param> /// <param name="table">Table HtmlNode</param> /// <param name="id">Identifies the train</param> /// <param name="elviraId"></param> /// <returns>List of parser statements</returns> private static List <ParserStatement> ProcessHeader(APIResponse response, HtmlNode table, ref TrainIdStatement?id, string?elviraId) { List <ParserStatement> ret = new List <ParserStatement>(); TrainType?type = null; var headerRow = table.ChildNodes.Where(n => n.Name == "tr").FirstOrDefault(); if (headerRow == null) { ret.Add(new ErrorStatement(response, ErrorTypes.NoTableRows)); return(ret); } var headerEnum = headerRow.ChildNodes.Elements().GetEnumerator(); if (!headerEnum.MoveNext()) { ret.Add(new ErrorStatement(response, ErrorTypes.HeaderEmpty)); return(ret); } var headerTextSplit = headerEnum.Current.InnerText.Split(new char[0], StringSplitOptions.RemoveEmptyEntries); if (id == null) { int?trainNumber = null; if (headerTextSplit.Length > 0) { trainNumber = CSExtensions.ParseInt(headerTextSplit[0]); } if (trainNumber != null) { ret.Add(id = new TrainIdStatement(response, trainNumber.Value, elviraId)); } else { ret.Add(new ErrorStatement(response, ErrorTypes.NoTrainIdentification)); } } if (id == null) { return(ret); } string?name = null; for (int i = 1; i < headerTextSplit.Length; i++) { if ((type = DetermineTrainType(headerTextSplit[i])) != null) { break; } else { if (name == null) { name = headerTextSplit[i]; } else { name += " " + headerTextSplit[i]; } } } ret.Add(new TrainNameStatement(response, id, name)); while (headerEnum.MoveNext()) { TrainType?detType = DetermineTrainType(headerEnum.Current); if (detType != null) { if (type != null) { type = detType; } } else if (headerEnum.Current.Name == "span" && headerEnum.Current.HasClass("viszszam2")) { ret.Add(new TrainViszStatement(response, id, headerEnum.Current.InnerText)); } else if (headerEnum.Current.Name == "font") { var relationText = headerEnum.Current.InnerText.Substr(1, -1).Split(',')[0].Trim(); var stationNames = relationText.Split(" - ").Select(s => s.Trim()).ToArray(); var from = new StationIdStatement(response, stationNames[0], null); var to = new StationIdStatement(response, stationNames[1], null); ret.Add(from); ret.Add(to); ret.Add(new TrainRelationStatement(response, id, from, to)); if (type != null) { ret.Add(new TrainTypeStatement(response, id, type.Value)); } } else if (headerEnum.Current.Name == "ul") { StationIdStatement?firstFrom = null; StationIdStatement?lastTo = null; foreach (HtmlNode li in headerEnum.Current.ChildNodes.Where(n => n.Name == "li")) { var liEnum = li.ChildNodes.AsEnumerable().GetEnumerator(); string? fromStation = null, toStation = null; TrainType?relType = null; if (liEnum.MoveNext()) { var text = liEnum.Current.InnerText.Trim(); var colonSplit = text.Split(':'); var relationSplit = colonSplit[0].Split(" - "); fromStation = relationSplit[0].Trim(); toStation = relationSplit[1].Trim(); relType = DetermineTrainType(colonSplit[1].Trim()); } if (liEnum.MoveNext()) { if (liEnum.Current.Name == "img") { relType = DetermineTrainType(liEnum.Current); } } if (fromStation != null && toStation != null && relType != null) { var from = new StationIdStatement(response, fromStation, null); if (firstFrom != null) { firstFrom = from; } var to = new StationIdStatement(response, toStation, null); lastTo = to; ret.Add(from); ret.Add(to); ret.Add(new TrainSubrelationStatement(response, id, from, to, relType.Value)); } } if (firstFrom != null && lastTo != null) { ret.Add(new TrainRelationStatement(response, id, firstFrom, lastTo)); } } } return(ret); }
static public void Generate(List <IRecordObject> recordObjects, string csFilePath) { var list = recordObjects.FindAll(x => x is ClassWithMembersAndTypes || x is SystemClassWithMembersAndTypes).ConvertAll(x => { GenerateInfo info = null; if (x is ClassWithMembersAndTypes) { var c = x as ClassWithMembersAndTypes; info = new GenerateInfo() { ClassInfo = c.ClassInfo, MemberTypeInfo = c.MemberTypeInfo }; } else if (x is SystemClassWithMembersAndTypes) { var c = x as SystemClassWithMembersAndTypes; info = new GenerateInfo() { ClassInfo = c.ClassInfo, MemberTypeInfo = c.MemberTypeInfo }; } if (info != null && info.ClassInfo != null) { //系统类跳过 if (info.ClassInfo.Name.Value.StartsWith("System")) { return(null); } } return(info); }); var builder = new StringBuilder(2048); builder.AppendLine("using System;"); builder.AppendLine("using System.Collections.Generic;"); builder.AppendLine(); foreach (var item in list) { if (item == null) { continue; } var tupleInfo = CSExtensions.GetNamespaceAndClassNames(item.ClassInfo.Name.Value); var memberCount = item.ClassInfo.MemberCount; var memberNames = item.ClassInfo.MemberNames.ToList().ConvertAll(x => x.Value); var binaryTypeEnums = item.MemberTypeInfo.BinaryTypeEnums; var additionalInfos = item.MemberTypeInfo.AdditionalInfos; var hasNamespace = !string.IsNullOrEmpty(tupleInfo.Item1); var tabIndex = 0; if (hasNamespace) { builder.AppendFormat("namespace {0}", tupleInfo.Item1); builder.AppendLine(); builder.AppendLine("{"); tabIndex++; } foreach (var className in tupleInfo.Item2) { builder.AppendFormat("{0}[System.Serializable]", new string('\t', tabIndex)); builder.AppendLine(); builder.AppendFormat("{0}class {1}", new string('\t', tabIndex), className); builder.AppendLine(); builder.AppendFormat("{0}{{", new string('\t', tabIndex)); builder.AppendLine(); tabIndex++; } { for (int i = 0; i < memberCount; i++) { var memberName = memberNames[i]; var binaryTypeEnum = binaryTypeEnums[i]; var additionalInfo = additionalInfos[i]; var memberType = string.Empty; switch (binaryTypeEnum) { case BinaryTypeEnumeration.Primitive: case BinaryTypeEnumeration.PrimitiveArray: memberType = "System." + additionalInfo.ToString(); break; case BinaryTypeEnumeration.String: memberType = "string"; break; case BinaryTypeEnumeration.Object: memberType = "object"; break; case BinaryTypeEnumeration.SystemClass: memberType = additionalInfo.ToString(); break; case BinaryTypeEnumeration.Class: var info = additionalInfo as ClassTypeInfo; memberType = info.TypeName.Value; break; default: throw new NotImplementedException("BinaryTypeEnumeration:" + binaryTypeEnum); } //generic var index = tupleInfo.Item3.IndexOf(memberType); if (index != -1) { memberType = "T" + index; } var isProperty = memberName.Contains(k_BackingField); if (isProperty) { var match = Regex.Match(memberName, string.Format("<(.*?)>{0}", k_BackingField)); memberName = match.Groups[1].Value; } if (CSExtensions.IsKeyword(memberName)) { memberName = "@" + memberName; } memberType = memberType.Replace("+", "."); builder.AppendFormat("{0}public {1} {2}{3}", new string('\t', tabIndex), memberType, memberName, isProperty ? " { set; get; }" : ";"); builder.AppendLine(); } } foreach (var className in tupleInfo.Item2) { tabIndex--; builder.AppendFormat("{0}}}", new string('\t', tabIndex)); builder.AppendLine(); } if (hasNamespace) { tabIndex--; builder.AppendLine("}"); builder.AppendLine(); } } File.WriteAllText(csFilePath, builder.ToString()); }