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
import (
"encoding/json"
"encoding/xml"
"errors"
"fmt"
"log"
"os"
"regexp"
"strconv"
)
type OsmBounds struct {
@ -38,6 +39,20 @@ type OsmTag struct {
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 {
Id int64 `xml:"id,attr"`
Version int32 `xml:"version,attr"`
@ -54,19 +69,37 @@ type OsmDocument struct {
Bounds OsmBounds `xml:"bounds"`
Nodes []OsmNode `xml:"node"`
Relations []OsmRelation `xml:"relation"`
Ways []OsmWay `xml:"way"`
}
type CombiData struct {
/// Name of the operator of the route.
/// E.g.: "C7 - AqpMasivo"
// Number that succeedes the Company name.
// E.g.: 7
Id int
// Name of the operator of the route.
// E.g.: "C7 - AqpMasivo"
Company string
/// Name of the route
/// E.g.: "Combi B: Villa Santa Rosa -> Terminal Terrestre"
// Name of the route
// E.g.: "Combi B: Villa Santa Rosa -> Terminal Terrestre"
Name string
/// Contains a single, identifiable name for the route.
/// This is the Name field, but without any extra info
/// E.g.: "B"
ParsedName string
// Indentifiable name of the route
Ref string
Color 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() {
@ -113,65 +146,101 @@ func main() {
// transform sitMembers into CombiData
combis := make([]CombiData, 0)
for _, member := range sitMembers {
var operatorTag *OsmTag
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,
})
combis = append(combis, parseCombiData(member))
}
// Create a map from string to CombiLine
combiLineMap := make(map[string]*CombiLine)
// Populate the map
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) {
// There are 3 types of route name formats:
// Combi xx : ____
// Curster xx : ____
// xx : ___
// attempt first format
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
// Extracts the id from a line name.
// E.g.: "C11 - Cotum" -> 11
func parseLineId(lineName string) int {
regex := regexp.MustCompile("C(\\d+) - .+")
groups := regex.FindStringSubmatch(lineName)
if groups == nil {
panic(fmt.Sprintf("Found an invalid line name (doesnt match format): %s", lineName))
}
// Return an error
return "", errors.New(fmt.Sprintf("Route %s did not match any pattern", routeName))
number, err := strconv.Atoi(groups[1])
if err != nil {
panic(err)
}
return number
}