Ejemplo n.º 1
0
        static void AssertAge(TitanicPassenger pax)
        {
            if (!pax.AgeMonths.HasValue || !pax.BirthDate.HasValue)
            {
                return;
            }

            int age1 = pax.AgeMonths.Value;
            int age2 = pax.BirthDate.Value.GetAgeMonths(Titanic.SunkDate);

            if (age1 == age2)
            {
                return;
            }

            throw new ModelValidationException($"Age mismatch: '{age1}' ≠ '{age2}'");
        }
Ejemplo n.º 2
0
        static List <TitanicPassenger> ParsePassengerListings(string zipPath)
        {
            List <TitanicPassenger> passengers = new List <TitanicPassenger>();

            using (var fstream = File.OpenRead(zipPath))
                using (var zip = new ZipArchive(fstream, ZipArchiveMode.Read))
                {
                    foreach (var zipEntry in zip.Entries.Where(e => e.IsRootFile()))
                    {
                        string        html    = zipEntry.ReadContentAsString();
                        IHtmlDocument htmlDoc = new HtmlParser().ParseDocument(html);

                        foreach (var tr in htmlDoc.QuerySelector("#manifest").QuerySelectorAll("tr"))
                        {
                            var pax   = new TitanicPassenger();
                            var cells = tr.QuerySelectorAll("td").ToArray();
                            if (cells.Length == 0)
                            {
                                continue;
                            }

                            pax.Url = cells[0].QuerySelector("a[itemprop=\"url\"]").GetAttribute("href");
                            pax.Id  = pax.Url.Trim('/').Split('/')[1].ToLower().Replace(".html", "");

                            pax.HasSurvived     = !pax.Url.StartsWith("/titanic-victim/");
                            pax.FamilyName      = cells[0].QuerySelector("*[itemprop=\"familyName\"]").TextContent;
                            pax.GivenName       = cells[0].QuerySelector("*[itemprop=\"givenName\"]").TextContent;
                            pax.HonorificPrefix = cells[0].QuerySelector("*[itemprop=\"honorificPrefix\"]").TextContent;

                            if (pax.HonorificPrefix.AnyOf("Doña", "Miss", "Mlle", "Mme.", "Ms", "Mrs", "Sra."))
                            {
                                pax.Sex = Sex.Female;
                            }
                            else if (pax.HonorificPrefix.AnyOf("Captain", "Col.", "Colonel", "Don.", "Dr", "Fr", "Major", "Master", "Mr", "Rev.", "Revd", "Sir", "Sr."))
                            {
                                pax.Sex = Sex.Male;
                            }
                            else
                            {
                                if (pax.FullName.EndsWith(", Lady") || pax.FullName.EndsWith(", Countess of"))
                                {
                                    pax.Sex = Sex.Female;
                                }
                            }
                            // Исключение
                            if (pax.HonorificPrefix == "Dr" && pax.FullName == "Dr LEADER, Alice May")
                            {
                                pax.Sex = Sex.Female;
                            }

                            string ageText = cells[1].TextContent.Trim();
                            pax.AgeMonths = ageText.Length == 0 ? null : ageText.EndsWith("m") ? (int?)int.Parse(ageText.TrimEnd('m')) : (int?)12 * int.Parse(ageText);

                            string classText = cells[2].TextContent;
                            if (classText.Contains("1st Class Passenger"))
                            {
                                pax.Class = Class.First;
                            }
                            else if (classText.Contains("2nd Class Passenger"))
                            {
                                pax.Class = Class.Second;
                            }
                            else if (classText.Contains("3rd Class Passenger"))
                            {
                                pax.Class = Class.Third;
                            }
                            else if (classText.Contains("Deck Crew"))
                            {
                                pax.Class = Class.DeckCrew;
                            }
                            else if (classText.Contains("Engineering Crew"))
                            {
                                pax.Class = Class.EngineeringCrew;
                            }
                            else if (classText.Contains("Victualling Crew"))
                            {
                                pax.Class = Class.VictuallingCrew;
                            }

                            pax.IsGuaranteeGroupMember = classText.Contains("H&W Guarantee Group");
                            if (classText.Contains("Servant"))
                            {
                                pax.IsServant = true;
                            }

                            pax.TicketNo    = cells[3].InnerHtml.Split("<br>")[0].Trim();
                            pax.TicketPrice = new Price(cells[3].InnerHtml.Split("<br>")[1].Trim());

                            pax.Boarded = (City)Enum.Parse(typeof(City), cells[4].TextContent);

                            pax.JobTitle = cells[5].TextContent.Replace("&nbsp;", "").Trim();
                            if (pax.JobTitle.Length == 0)
                            {
                                //if (classText.Contains("Servant")) pax.Job = "Servant";
                            }

                            string lifeboatText = cells[6].TextContent.Trim();
                            pax.Lifeboat = lifeboatText.Length > 0 && !lifeboatText.Contains("[") ? lifeboatText : null;
                            passengers.Add(pax);
                        }
                    }
                }

            return(passengers);
        }