diff --git a/main.go b/main.go index 39c0bed..67cfd06 100644 --- a/main.go +++ b/main.go @@ -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 }