Example #1
0
        public static void FixAddrStreetFormat()
        {
            // or @"C:\Users\Alex\Downloads\Maine\maine-latest.osm\maine-latest.osm"
            var osm       = OpenFile(@"C:\Users\Alex\Downloads\Maine\maine-latest-internal.osm.pbf");
            var index     = osm.ToDictionary(e => new OsmGeoKey(e));
            var stringdex = index.Values.ToDictionary(e => e.Type.ToString() + e.Id);
            var canonNamesToCompleteWays = index.Values
                                           .OfType <Way>()
                                           .Where(e => e.Tags != null && e.Tags.ContainsKey("highway") && e.Tags.ContainsKey("name"))
                                           .Select(w => w.AsComplete(stringdex))
                                           .GroupBy(e => Connonical(e.Tags["name"]))
                                           .ToDictionary();

            var addrStreets = index.Values.Where(e => e.Tags != null && e.Tags.Contains("addr:state", "ME") && e.Tags.ContainsKey("addr:street"))
                              .Select(element => new { element, addrStreet = element.Tags["addr:street"], canon = Connonical(element.Tags["addr:street"]), position = element.AsComplete(stringdex).AsPosition() })
                              .Where(e => canonNamesToCompleteWays.ContainsKey(e.canon))
                              .ToArray();

            var changes = new List <OsmGeo>();

            foreach (var addr in addrStreets)
            {
                var roadMatches = canonNamesToCompleteWays[addr.canon]
                                  .Where(r => Geometry.MinDistanceMeters(addr.position, r) < 1000).ToArray();
                var roadNameMatches = roadMatches.Select(r => r.Tags["name"]).Distinct().ToArray();
                if (roadNameMatches.Length == 0)
                {
                }
                else if (roadNameMatches.Length > 1)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("conflict " + addr.element.Type + " " + addr.element.Id + " -> " + string.Join(", ", roadNameMatches));
                    Console.ForegroundColor = ConsoleColor.White;

                    roadMatches.First().Tags.Add("fixme",
                                                 "Different road segments have name formats conflict. Check the street sign and fix: " +
                                                 string.Join(" vs ", roadNameMatches.Select(n => '[' + n + ']')));
                    //changes.Add(roadMatches.First().AsSimple());
                }
                else if (roadNameMatches[0] != addr.addrStreet)
                {
                    //if (WhitespacesDiffers(addr.addrStreet, roadNameMatches[0]) && addr.element.UserName.StartsWith("blackboxlogic"))
                    //{
                    //	var did = false;
                    //	foreach (var road in roadMatches)
                    //	{
                    //		if (!road.Tags.Contains("official_name", addr.addrStreet))
                    //		{
                    //			did = true;
                    //			road.Tags.AddOrReplace("official_name", addr.addrStreet);
                    //			changes.Add(road.AsOsmGeo());
                    //		}
                    //	}

                    //	if (did) Console.WriteLine("O\t" + roadMatches.Length + "x " + roadNameMatches.First() + " -> " + addr.addrStreet);
                    //}

                    Console.WriteLine(addr.addrStreet + " -> " + roadNameMatches.First());
                    addr.element.Tags["addr:street"] = roadNameMatches.First();
                    changes.Add(addr.element);
                }
            }

            var change = Changes.FromGeos(null, changes, null);
            var ids    = Subjects.UploadChange(change, GetCommitTags("Adjusting addr:street format to match nearby street name (case, punctuation, space)"), "Fix addrStreet Format").Result;
            //var streetNameConflicts = connonicalStreetNames.Where(c => c.Value.Length > 1)
            //	.ToDictionary(c => c.Key, c => FightingWays(c.Value.SelectMany(n => streetNamesToWays[n].Ways)));
            //Console.WriteLine(string.Join(Environment.NewLine,
            //	streetNameConflicts.Where(kvp => kvp.Value.Any()).Select(kvp => kvp.Key + ": " + "\n\t" +
            //		string.Join("\n\t", kvp.Value.Select(w => "osm.org/way/" + w.Id + "\t" + wayIndex[w.Id].Tags["name"])))));
        }
        // nohousenumber=yes
        // consider just leaving out all addr:unit=*
        // option to moveNode or not. (Do you trust E911 locations more than OSM?)
        // MatchWidth list to handle multi-match

        // Maybe fix addr:street punctuation on elements that I didn't add or update
        // Maybe fix addr:street should be addr:place on elements that I didn't add or update
        // Maybe fix nodes merging into buildings on elements that I didn't add or update
        public void Main()
        {
            Static.Municipalities = FileSerializer.ReadJsonCacheOrSource("MaineMunicipalities.json",
                                                                         GetMunicipalities).Result;
            ShowProgress();
            Municipality = Static.Municipalities.Values.First(m => !m.ChangeSetIds.Any()).Name;
            Console.WriteLine("Starting in " + Municipality);

            while (true)
            {
                Console.Write("> ");
                var userInput = Console.ReadLine();

                if (Is(userInput, "reference"))
                {
                    //Func<Feature, bool> filter = f => (f.Geometry as Point).Coordinates.Longitude >= -70.505;
                    var reference = References.Fetch(Municipality).Result;
                    FileSerializer.WriteXml(Municipality + "/Reference.osm", reference);
                    File.Delete(Municipality + "/Conflated.osc");
                }
                else if (Is(userInput, "review ref"))
                {
                    var reference = GetReference();
                    References.Report(reference.GetElements().ToArray());
                }
                else if (Is(userInput, "subject"))
                {
                    var reference = GetReference();
                    var subject   = Subjects.GetElementsInBoundingBox(reference.Bounds.ExpandBy(15));
                    FileSerializer.WriteXml(Municipality + "/Subject.osm", subject);
                    File.Delete(Municipality + "/Conflated.osc");
                    Console.WriteLine("ChangeId high watermark: " + subject.GetHighestChangeSetId());
                }
                else if (Is(userInput, "conflate"))
                {
                    DoConflate();
                }
                else if (Is(userInput, "review con"))
                {
                    Conflate.Review(Municipality);
                }
                else if (Is(userInput, "review"))
                {
                    OpenJosm();
                }
                else if (Is(userInput, "list"))
                {
                    var key       = userInput.Split(" ")[1];
                    var reference = GetReference();
                    var values    = reference.GetElements().Where(e => e.Tags.ContainsKey(key)).Select(e => "\n\t" + e.Tags[key]).GroupBy(n => n).ToArray();

                    Console.WriteLine(string.Concat(values.Select(v => v.Key + "\tx" + v.Count())));
                }
                else if (Is(userInput, "filter"))
                {
                    var key       = userInput.Split(" ")[1];
                    var reference = GetReference();
                    DoFilter(key, reference.GetElements());
                    File.Delete(Municipality + "/Reference.osm");
                    File.Delete(Municipality + "/Conflated.osc");
                }
                else if (Is(userInput, "note"))
                {
                    Static.Municipalities[Municipality].Notes += "/n" + userInput.Split(' ', 2)[1];
                    FileSerializer.WriteJson("MaineMunicipalities.json", Static.Municipalities);
                }
                else if (Is(userInput, "WhiteAll"))
                {
                    var review    = FileSerializer.ReadXml <Osm>(Municipality + "/Conflated.Review.osm");
                    var selection = review.GetElements()
                                    .Where(e => e.Tags != null && e.Tags.ContainsKey(Static.maineE911id))
                                    .Select(e => e.Tags[Static.maineE911id])
                                    .SelectMany(id => id.Split(new char[] { ' ', ',', ';', '-' }, StringSplitOptions.RemoveEmptyEntries))
                                    .Select(long.Parse)
                                    .Except(Static.Municipalities[Municipality].WhiteList)
                                    .ToArray();
                    Static.Municipalities[Municipality].WhiteList.AddRange(selection);

                    FileSerializer.WriteJson("MaineMunicipalities.json", Static.Municipalities);
                    File.Delete(Municipality + "/Conflated.osc");
                }
                else if (Is(userInput, "white"))
                {
                    var selection = userInput.Split(' ', 2)[1]
                                    .Split(new char[] { ' ', ',', ';', '-', '=' }, StringSplitOptions.RemoveEmptyEntries)
                                    .Where(c => long.TryParse(c, out _))
                                    .Select(long.Parse)
                                    .Except(Static.Municipalities[Municipality].WhiteList)
                                    .ToArray();
                    Static.Municipalities[Municipality].WhiteList.AddRange(selection);

                    FileSerializer.WriteJson("MaineMunicipalities.json", Static.Municipalities);
                    File.Delete(Municipality + "/Conflated.osc");
                }
                else if (Is(userInput, "blacktag"))
                {
                    var tag = userInput.Split(' ', 2)[1].Replace("maineE911id=", "");
                    Static.Municipalities[Municipality].BlackTags.Add(tag);
                    Static.Municipalities[Municipality].BlackTags = Static.Municipalities[Municipality].BlackTags.Distinct().ToList();
                    FileSerializer.WriteJson("MaineMunicipalities.json", Static.Municipalities);
                    File.Delete(Municipality + "/Reference.osm");
                    File.Delete(Municipality + "/Conflated.osc");
                }
                else if (Is(userInput, "black"))
                {
                    AddToList(userInput.Split(' ', 2)[1], Static.Municipalities[Municipality].BlackList);
                    FileSerializer.WriteJson("MaineMunicipalities.json", Static.Municipalities);
                    File.Delete(Municipality + "/Reference.osm");
                    File.Delete(Municipality + "/Conflated.osc");
                }
                else if (Is(userInput, "ignore"))
                {
                    AddToList(userInput.Split(' ', 2)[1], Static.Municipalities[Municipality].IgnoreList);
                    FileSerializer.WriteJson("MaineMunicipalities.json", Static.Municipalities);
                }
                else if (Is(userInput, "commit"))
                {
                    var change  = FileSerializer.ReadXml <OsmChange>(Municipality + "/Conflated.osc");
                    var results = Subjects.UploadChange(change, Municipality).Result;
                    Static.Municipalities[Municipality].ChangeSetIds.AddRange(results);
                    Static.Municipalities[Municipality].ImportDate = DateTime.UtcNow;
                    FileSerializer.WriteJson("MaineMunicipalities.json", Static.Municipalities);
                    Console.WriteLine("Finished!");

                    Next();
                }
                else if (Is(userInput, "skip"))
                {
                    Static.Municipalities[Municipality].Notes += " SKIPPED";
                    Static.Municipalities[Municipality].ChangeSetIds.Add(-1);
                    FileSerializer.WriteJson("MaineMunicipalities.json", Static.Municipalities);
                }
                else if (Is(userInput, "next"))
                {
                    Next();
                }
                else if (Is(userInput, "switch"))
                {
                    Municipality = ChooseMunicipality();
                    ShowProgress();
                }
                else if (Is(userInput, "folder"))
                {
                    OpenExplorer();
                }
                else if (Is(userInput, "remind"))
                {
                    var parts     = userInput.Split(' ', 3);
                    var id        = long.Parse(parts[1].Replace("maineE911id=", ""));
                    var reference = GetReference();
                    var element   = reference.Nodes.First(e => Math.Abs(e.Id.Value) == Math.Abs(id));
                    var message   = parts.Length > 2 ? parts[2] : "The addresses imported on this neighborhood need to be aligned with the correct buildings";
                    Subjects.CreateNote(element.Latitude.Value, element.Longitude.Value, message).Wait();
                }
                else if (Is(userInput, "help"))
                {
                    Console.WriteLine("Options:");
                    Console.WriteLine("\tSwitch");
                    Console.WriteLine("\tNext");
                    Console.WriteLine("\tReference");
                    Console.WriteLine("\tReview Reference");
                    Console.WriteLine("\tSubject");
                    Console.WriteLine("\tConflate");
                    Console.WriteLine("\tReview Conflate");
                    Console.WriteLine("\tReview");
                    Console.WriteLine("\tList [key]");
                    Console.WriteLine("\tFilter [key]");
                    Console.WriteLine("\t\t[Y/N/AUnit/Descr/Build/Move]");
                    Console.WriteLine("\tNote [message]");
                    Console.WriteLine("\tWhitelist [###]<,[###]...>");
                    Console.WriteLine("\tWhiteAll");
                    Console.WriteLine("\tBlacklist [###]<,[###]...>");
                    Console.WriteLine("\tBlackTag [###].[key] || *.[key]=[value]");
                    Console.WriteLine("\tIgnore [###]<,[###]...>");
                    Console.WriteLine("\tRemind [ref###] <message>");
                    Console.WriteLine("\tCommit");
                }
                else
                {
                    Console.WriteLine("What?");
                }

                Console.WriteLine("Done");
            }
        }