コード例 #1
0
        /// <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);
            }
        }
コード例 #2
0
 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";
 }
コード例 #3
0
        /// <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);
        }
コード例 #4
0
        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));
            }
        }
コード例 #5
0
        /// <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()));
            }
        }
コード例 #6
0
        /// <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);
        }
コード例 #7
0
        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());
        }