Parse routes not indexed by the root SIT element
This commit is contained in:
parent
ddda0706e4
commit
3b2c7da296
163
main.go
163
main.go
@ -7,6 +7,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -72,6 +73,11 @@ type OsmDocument struct {
|
|||||||
Ways []OsmWay `xml:"way"`
|
Ways []OsmWay `xml:"way"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CombiPair struct {
|
||||||
|
Departure *OsmRelation
|
||||||
|
Return *OsmRelation
|
||||||
|
}
|
||||||
|
|
||||||
type CombiData struct {
|
type CombiData struct {
|
||||||
// Number that succeedes the Company name.
|
// Number that succeedes the Company name.
|
||||||
// E.g.: 7
|
// E.g.: 7
|
||||||
@ -83,9 +89,10 @@ type CombiData struct {
|
|||||||
// E.g.: "Combi B: Villa Santa Rosa -> Terminal Terrestre"
|
// E.g.: "Combi B: Villa Santa Rosa -> Terminal Terrestre"
|
||||||
Name string
|
Name string
|
||||||
// Indentifiable name of the route
|
// Indentifiable name of the route
|
||||||
Ref string
|
Ref string
|
||||||
Color string
|
Color string
|
||||||
Members *[]OsmMember
|
Members *[]OsmMember
|
||||||
|
ReturnMembers *[]OsmMember
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type to be consumed by the client
|
// Type to be consumed by the client
|
||||||
@ -128,36 +135,13 @@ func main() {
|
|||||||
nodesMap[node.Id] = &node
|
nodesMap[node.Id] = &node
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the relation with id 17642638,
|
// Contains a list of pairs of relations
|
||||||
// that relation hosts the SIT data
|
sitMembers := getSITRelations(&osmDocument)
|
||||||
var sitId int64 = 17642638
|
|
||||||
var sitRelation *OsmRelation
|
|
||||||
for _, relation := range osmDocument.Relations {
|
|
||||||
if relation.Id == sitId {
|
|
||||||
sitRelation = &relation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if sitRelation == nil {
|
|
||||||
panic("SIT relation with id 17642638 not found!")
|
|
||||||
}
|
|
||||||
|
|
||||||
// (naively) get all the submembers
|
|
||||||
sitMembers := make([]OsmRelation, 0)
|
|
||||||
for _, member := range sitRelation.Members {
|
|
||||||
// search the member
|
|
||||||
// TODO: determine if this is a performance bottleneck,
|
|
||||||
// and requires optimization (insertion sort & binary search)
|
|
||||||
for _, relation := range osmDocument.Relations {
|
|
||||||
if relation.Id == member.Ref {
|
|
||||||
sitMembers = append(sitMembers, relation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// transform sitMembers into CombiData
|
// transform sitMembers into CombiData
|
||||||
combis := make([]CombiData, 0)
|
combis := make([]CombiData, 0)
|
||||||
for _, member := range sitMembers {
|
for _, memberPair := range sitMembers {
|
||||||
combis = append(combis, parseCombiData(member))
|
combis = append(combis, parseCombiData(memberPair))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a map from string to CombiLine
|
// Create a map from string to CombiLine
|
||||||
@ -188,11 +172,10 @@ func main() {
|
|||||||
// Convert each CombiData into a CombiRoute and store it
|
// Convert each CombiData into a CombiRoute and store it
|
||||||
for _, combi := range combis {
|
for _, combi := range combis {
|
||||||
log.Printf("Processing %s %s", combi.Company, combi.Ref)
|
log.Printf("Processing %s %s", combi.Company, combi.Ref)
|
||||||
returnCoord := make([][]float64, 0)
|
|
||||||
combiRoute := CombiRoute{
|
combiRoute := CombiRoute{
|
||||||
Name: combi.Ref,
|
Name: combi.Ref,
|
||||||
Departure: getCoordinates(&osmDocument.Ways, nodesMap, combi.Members),
|
Departure: getCoordinates(&osmDocument.Ways, nodesMap, combi.Members),
|
||||||
Return: &returnCoord,
|
Return: getCoordinates(&osmDocument.Ways, nodesMap, combi.ReturnMembers),
|
||||||
}
|
}
|
||||||
combiLineSlice := combiRoutesMap[combi.Id]
|
combiLineSlice := combiRoutesMap[combi.Id]
|
||||||
combiLineSlice.Routes = append(combiLineSlice.Routes, combiRoute)
|
combiLineSlice.Routes = append(combiLineSlice.Routes, combiRoute)
|
||||||
@ -348,6 +331,10 @@ func writeOutput(lines map[string]*CombiLine, routes map[int]*CombiRouteContaine
|
|||||||
for _, combiLine := range lines {
|
for _, combiLine := range lines {
|
||||||
combiLineSlice = append(combiLineSlice, combiLine)
|
combiLineSlice = append(combiLineSlice, combiLine)
|
||||||
}
|
}
|
||||||
|
// sort the map
|
||||||
|
sort.Slice(combiLineSlice, func(i, j int) bool {
|
||||||
|
return combiLineSlice[i].Id < combiLineSlice[j].Id
|
||||||
|
})
|
||||||
|
|
||||||
// print JSON
|
// print JSON
|
||||||
jsonBytes, err := json.Marshal(combiLineSlice)
|
jsonBytes, err := json.Marshal(combiLineSlice)
|
||||||
@ -361,6 +348,9 @@ func writeOutput(lines map[string]*CombiLine, routes map[int]*CombiRouteContaine
|
|||||||
//
|
//
|
||||||
for lineId, routeContainer := range routes {
|
for lineId, routeContainer := range routes {
|
||||||
outFilename := fmt.Sprintf("output/routes_%d.json", lineId)
|
outFilename := fmt.Sprintf("output/routes_%d.json", lineId)
|
||||||
|
sort.Slice(routeContainer.Routes, func(i, j int) bool {
|
||||||
|
return routeContainer.Routes[i].Name < routeContainer.Routes[j].Name
|
||||||
|
})
|
||||||
jsonBytes, err := json.Marshal(routeContainer.Routes)
|
jsonBytes, err := json.Marshal(routeContainer.Routes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(nil)
|
panic(nil)
|
||||||
@ -375,7 +365,10 @@ func writeOutput(lines map[string]*CombiLine, routes map[int]*CombiRouteContaine
|
|||||||
log.Print("JSON files written to output/")
|
log.Print("JSON files written to output/")
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseCombiData(member OsmRelation) CombiData {
|
func parseCombiData(combiPair *CombiPair) CombiData {
|
||||||
|
member := combiPair.Departure
|
||||||
|
returnMember := combiPair.Return
|
||||||
|
|
||||||
var operatorTag *OsmTag
|
var operatorTag *OsmTag
|
||||||
var nameTag *OsmTag
|
var nameTag *OsmTag
|
||||||
var refTag *OsmTag
|
var refTag *OsmTag
|
||||||
@ -414,15 +407,107 @@ func parseCombiData(member OsmRelation) CombiData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return CombiData{
|
return CombiData{
|
||||||
Id: parseLineId(operatorTag.V),
|
Id: parseLineId(operatorTag.V),
|
||||||
Company: operatorTag.V,
|
Company: operatorTag.V,
|
||||||
Name: nameTag.V,
|
Name: nameTag.V,
|
||||||
Ref: refTag.V,
|
Ref: refTag.V,
|
||||||
Color: colorTag.V,
|
Color: colorTag.V,
|
||||||
Members: &member.Members,
|
Members: &member.Members,
|
||||||
|
ReturnMembers: &returnMember.Members,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finds all the relations that are related to the SIT
|
||||||
|
func getSITRelations(osmDocument *OsmDocument) []*CombiPair {
|
||||||
|
// a route is identified by the pair operator,ref
|
||||||
|
|
||||||
|
// how to know which route is the departure,
|
||||||
|
// and which is the return?
|
||||||
|
// each district (route, color) is assigned to a district/area
|
||||||
|
// in arequipa,
|
||||||
|
// so to know which way is each route, we compare the first
|
||||||
|
// coordinate against a coordinate located at that district
|
||||||
|
// TODO: implement that
|
||||||
|
|
||||||
|
// map of maps
|
||||||
|
// map of `operator` to (map of `ref` to OsmRelation)
|
||||||
|
operators := make(map[string]*(map[string]*[]*OsmRelation))
|
||||||
|
|
||||||
|
// search, filter and store
|
||||||
|
for _, r := range osmDocument.Relations {
|
||||||
|
if r.Tag("type", "route") && r.Tag("route", "bus") && r.Tag("network", "SIT") {
|
||||||
|
operator := r.GetTag("operator")
|
||||||
|
ref := r.GetTag("ref")
|
||||||
|
|
||||||
|
// check if operator map exists, create if not
|
||||||
|
operatorMap := operators[operator]
|
||||||
|
if operatorMap == nil {
|
||||||
|
newMap := make(map[string]*[]*OsmRelation)
|
||||||
|
operatorMap = &newMap
|
||||||
|
operators[operator] = &newMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if ref exists, create if not
|
||||||
|
refs := (*operatorMap)[ref]
|
||||||
|
if refs == nil {
|
||||||
|
refsArr := make([]*OsmRelation, 0)
|
||||||
|
refs = &refsArr
|
||||||
|
(*operatorMap)[ref] = &refsArr
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert
|
||||||
|
*refs = append(*refs, &r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// map and filter
|
||||||
|
pairs := make([]*CombiPair, 0)
|
||||||
|
for operatorKey, operator := range operators {
|
||||||
|
for refKey, relationSlice := range *operator {
|
||||||
|
if len(*relationSlice) != 2 {
|
||||||
|
log.Printf("operator(%s) ref(%s): expected 2 ref elements, found %d", operatorKey, refKey, len(*relationSlice))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// AYAYA!
|
||||||
|
newPair := CombiPair{
|
||||||
|
Departure: (*relationSlice)[0],
|
||||||
|
Return: (*relationSlice)[1],
|
||||||
|
}
|
||||||
|
pairs = append(pairs, &newPair)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pairs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *OsmRelation) HasTag(tagName string) bool {
|
||||||
|
for _, tag := range r.Tags {
|
||||||
|
if tag.K == tagName {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *OsmRelation) Tag(tagName string, tagValue string) bool {
|
||||||
|
for _, tag := range r.Tags {
|
||||||
|
if tag.K == tagName && tag.V == tagValue {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *OsmRelation) GetTag(tagName string) string {
|
||||||
|
for _, tag := range r.Tags {
|
||||||
|
if tag.K == tagName {
|
||||||
|
return tag.V
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("Tried to get, from relation(%d), tag %s, but it was not found", r.Id, tagName))
|
||||||
|
}
|
||||||
|
|
||||||
// Extracts the id from a line name.
|
// Extracts the id from a line name.
|
||||||
// E.g.: "C11 - Cotum" -> 11
|
// E.g.: "C11 - Cotum" -> 11
|
||||||
func parseLineId(lineName string) int {
|
func parseLineId(lineName string) int {
|
||||||
|
Loading…
Reference in New Issue
Block a user