Generate CombiLine JSON data

master
Araozu 2024-09-10 12:00:28 -05:00
parent d4a380c234
commit 3f38224d1e
1 changed files with 131 additions and 62 deletions

193
main.go
View File

@ -1,12 +1,13 @@
package main package main
import ( import (
"encoding/json"
"encoding/xml" "encoding/xml"
"errors"
"fmt" "fmt"
"log" "log"
"os" "os"
"regexp" "regexp"
"strconv"
) )
type OsmBounds struct { type OsmBounds struct {
@ -38,6 +39,20 @@ type OsmTag struct {
V string `xml:"v,attr"` V string `xml:"v,attr"`
} }
type OsmWay struct {
Id int64 `xml:"id,attr"`
Version int64 `xml:"version,attr"`
Timestamp string `xml:"timestamp,attr"`
Changeset int64 `xml:"changeset,attr"`
Uid int64 `xml:"uid,attr"`
User string `xml:"user,attr"`
Nds []OsmNd `xml:"nd"`
}
type OsmNd struct {
Ref int64 `xml:"ref,attr"`
}
type OsmRelation struct { type OsmRelation struct {
Id int64 `xml:"id,attr"` Id int64 `xml:"id,attr"`
Version int32 `xml:"version,attr"` Version int32 `xml:"version,attr"`
@ -54,19 +69,37 @@ type OsmDocument struct {
Bounds OsmBounds `xml:"bounds"` Bounds OsmBounds `xml:"bounds"`
Nodes []OsmNode `xml:"node"` Nodes []OsmNode `xml:"node"`
Relations []OsmRelation `xml:"relation"` Relations []OsmRelation `xml:"relation"`
Ways []OsmWay `xml:"way"`
} }
type CombiData struct { type CombiData struct {
/// Name of the operator of the route. // Number that succeedes the Company name.
/// E.g.: "C7 - AqpMasivo" // E.g.: 7
Id int
// Name of the operator of the route.
// E.g.: "C7 - AqpMasivo"
Company string Company string
/// Name of the route // Name of the route
/// E.g.: "Combi B: Villa Santa Rosa -> Terminal Terrestre" // E.g.: "Combi B: Villa Santa Rosa -> Terminal Terrestre"
Name string Name string
/// Contains a single, identifiable name for the route. // Indentifiable name of the route
/// This is the Name field, but without any extra info Ref string
/// E.g.: "B" Color string
ParsedName string }
// Type to be consumed by the client
// Represents a single company
type CombiLine struct {
Id int `json:"id"`
Name string `json:"name"`
District string `json:"district"`
Color string `json:"color"`
}
type CombiRoute struct {
Name string `json:"name"`
Departure []float64 `json:"departure"`
Return []float64 `json:"return"`
} }
func main() { func main() {
@ -113,65 +146,101 @@ func main() {
// transform sitMembers into CombiData // transform sitMembers into CombiData
combis := make([]CombiData, 0) combis := make([]CombiData, 0)
for _, member := range sitMembers { for _, member := range sitMembers {
var operatorTag *OsmTag combis = append(combis, parseCombiData(member))
var nameTag *OsmTag
for _, tag := range member.Tags {
if tag.K == "operator" {
operatorTag = &tag
continue
}
if tag.K == "name" {
nameTag = &tag
continue
}
}
if operatorTag == nil {
log.Fatalf("Found a SIT member without an operator tag, with id %d\n", member.Id)
}
if nameTag == nil {
log.Fatalf("Found a SIT member without a name tag, with id %d\n", member.Id)
}
parsedName, err := parseRoute(nameTag.V)
if err != nil {
log.Printf("SIT member id: %s\n", member.Id)
panic(err)
}
combis = append(combis, CombiData{
Company: operatorTag.V,
Name: nameTag.V,
ParsedName: parsedName,
})
} }
// Create a map from string to CombiLine
combiLineMap := make(map[string]*CombiLine)
// Populate the map
for _, combi := range combis { for _, combi := range combis {
log.Printf("%s: `%s`\n", combi.Company, combi.ParsedName) combiLine := combiLineMap[combi.Company]
if combiLine == nil {
// create the company in the map
combiLine := CombiLine{
Id: combi.Id,
Name: combi.Company,
District: "",
Color: combi.Color,
}
combiLineMap[combi.Company] = &combiLine
}
}
// convert the map into an array
combiLineSlice := make([]*CombiLine, 0)
for _, combiLine := range combiLineMap {
combiLineSlice = append(combiLineSlice, combiLine)
}
// print JSON
jsonStr, err := json.Marshal(combiLineSlice)
if err != nil {
panic(err)
}
fmt.Print(string(jsonStr[:]))
}
func parseCombiData(member OsmRelation) CombiData {
var operatorTag *OsmTag
var nameTag *OsmTag
var refTag *OsmTag
var colorTag *OsmTag
for _, tag := range member.Tags {
if tag.K == "operator" {
operatorTag = &tag
continue
}
if tag.K == "name" {
nameTag = &tag
continue
}
if tag.K == "ref" {
refTag = &tag
continue
}
if tag.K == "colour" {
colorTag = &tag
continue
}
}
if operatorTag == nil {
log.Fatalf("Found a SIT member without an operator tag, with id %d\n", member.Id)
}
if nameTag == nil {
log.Fatalf("Found a SIT member without a name tag, with id %d\n", member.Id)
}
if refTag == nil {
log.Fatalf("Found a SIT member without a ref tag, with id %d\n", member.Id)
}
if colorTag == nil {
log.Fatalf("Found a SIT member without a colour tag, with id %d\n", member.Id)
}
return CombiData{
Id: parseLineId(operatorTag.V),
Company: operatorTag.V,
Name: nameTag.V,
Ref: refTag.V,
Color: colorTag.V,
} }
} }
func parseRoute(routeName string) (string, error) { // Extracts the id from a line name.
// There are 3 types of route name formats: // E.g.: "C11 - Cotum" -> 11
// Combi xx : ____ func parseLineId(lineName string) int {
// Curster xx : ____ regex := regexp.MustCompile("C(\\d+) - .+")
// xx : ___ groups := regex.FindStringSubmatch(lineName)
if groups == nil {
// attempt first format panic(fmt.Sprintf("Found an invalid line name (doesnt match format): %s", lineName))
match := regexp.MustCompile("Combi (.+) :.+").FindStringSubmatch(routeName)
if match != nil {
return match[1], nil
}
match = regexp.MustCompile("Custer (.+) :.+").FindStringSubmatch(routeName)
if match != nil {
return match[1], nil
}
match = regexp.MustCompile("(.+) :.+").FindStringSubmatch(routeName)
if match != nil {
return match[1], nil
} }
// Return an error number, err := strconv.Atoi(groups[1])
return "", errors.New(fmt.Sprintf("Route %s did not match any pattern", routeName)) if err != nil {
panic(err)
}
return number
} }