diff --git a/cmd/run.go b/cmd/run.go index 9549cf1..2551bd4 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -5,8 +5,11 @@ import ( "encoding/json" "flag" "fmt" + "log" "os" "path" + "slices" + "strings" ) func Run(ctx context.Context) error { @@ -14,6 +17,8 @@ func Run(ctx context.Context) error { searchRadius := fs.Float64("r", 5.0, "search radius in miles") area := fs.Float64("a", 0.5, "result radius in miles") doArea := fs.Bool("d", false, "do result radius in miles") + var towns FlagStringArray + fs.Var(&towns, "t", "list of towns to search around") if err := fs.Parse(os.Args[1:]); err != nil { panic(err) } @@ -21,16 +26,6 @@ func Run(ctx context.Context) error { radiusX := 2 * radius / 2 radiusY := 2 * radius / 3 - m, err := NewMapsOf(ctx, fs.Args()[0]) - if err != nil { - return err - } - - results, err := m.Search(ctx, fs.Args()[1], *searchRadius) - if err != nil { - return err - } - type geoJson struct { Type string `json:"type"` Properties struct { @@ -41,24 +36,46 @@ func Run(ctx context.Context) error { Coordinates []any `json:"coordinates"` } `json:"geometry"` } - geoJsons := make([]geoJson, len(results)) - for i := range results { - geoJsons[i].Type = "Feature" - geoJsons[i].Properties.Name = path.Join(fs.Args()[1], results[i].Name) - geoJsons[i].Geometry.Type = "Point" - geoJsons[i].Geometry.Coordinates = []any{results[i].Lng, results[i].Lat} - if *doArea { - geoJsons[i].Geometry.Type = "Polygon" - x, y := results[i].Lng, results[i].Lat - geoJsons[i].Geometry.Coordinates = []any{[]any{ - [2]float64{x, y + radiusY}, // top - [2]float64{x + radiusX, y}, // right - [2]float64{x, y - radiusY}, // bot - [2]float64{x - radiusX, y}, // left - [2]float64{x, y + radiusY}, // top - }} + geoJsons := []geoJson{} + for _, town := range towns { + m, err := NewMapsOf(ctx, town) + if err != nil { + return err + } + + results, err := m.Search(ctx, fs.Args()[0], *searchRadius) + if err != nil { + return err + } + + for i := range results { + var a geoJson + a.Type = "Feature" + a.Properties.Name = path.Join(fs.Args()[0], results[i].Name) + a.Geometry.Type = "Point" + a.Geometry.Coordinates = []any{results[i].Lng, results[i].Lat} + if *doArea { + a.Geometry.Type = "Polygon" + x, y := results[i].Lng, results[i].Lat + a.Geometry.Coordinates = []any{[]any{ + [2]float64{x, y + radiusY}, // top + [2]float64{x + radiusX, y}, // right + [2]float64{x, y - radiusY}, // bot + [2]float64{x - radiusX, y}, // left + [2]float64{x, y + radiusY}, // top + }} + } + geoJsons = append(geoJsons, a) } } + log.Println(len(geoJsons)) + slices.SortFunc(geoJsons, func(a, b geoJson) int { + return strings.Compare(fmt.Sprint(a.Geometry.Coordinates), fmt.Sprint(b.Geometry.Coordinates)) + }) + geoJsons = slices.CompactFunc(geoJsons, func(a, b geoJson) bool { + return fmt.Sprint(a.Geometry.Coordinates) == fmt.Sprint(b.Geometry.Coordinates) + }) + log.Println("COMPACTED", len(geoJsons)) b, _ := json.Marshal(map[string]any{ "features": geoJsons, "type": "FeatureCollection", @@ -67,3 +84,14 @@ func Run(ctx context.Context) error { return ctx.Err() } + +type FlagStringArray []string + +func (array *FlagStringArray) String() string { + return strings.Join(*array, ", ") +} + +func (array *FlagStringArray) Set(s string) error { + *array = append(*array, s) + return nil +}