Parse routes not indexed by the root SIT element
This commit is contained in:
parent
ddda0706e4
commit
3b2c7da296
145
main.go
145
main.go
@ -7,6 +7,7 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
@ -72,6 +73,11 @@ type OsmDocument struct {
|
||||
Ways []OsmWay `xml:"way"`
|
||||
}
|
||||
|
||||
type CombiPair struct {
|
||||
Departure *OsmRelation
|
||||
Return *OsmRelation
|
||||
}
|
||||
|
||||
type CombiData struct {
|
||||
// Number that succeedes the Company name.
|
||||
// E.g.: 7
|
||||
@ -86,6 +92,7 @@ type CombiData struct {
|
||||
Ref string
|
||||
Color string
|
||||
Members *[]OsmMember
|
||||
ReturnMembers *[]OsmMember
|
||||
}
|
||||
|
||||
// Type to be consumed by the client
|
||||
@ -128,36 +135,13 @@ func main() {
|
||||
nodesMap[node.Id] = &node
|
||||
}
|
||||
|
||||
// Get the relation with id 17642638,
|
||||
// that relation hosts the SIT data
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Contains a list of pairs of relations
|
||||
sitMembers := getSITRelations(&osmDocument)
|
||||
|
||||
// transform sitMembers into CombiData
|
||||
combis := make([]CombiData, 0)
|
||||
for _, member := range sitMembers {
|
||||
combis = append(combis, parseCombiData(member))
|
||||
for _, memberPair := range sitMembers {
|
||||
combis = append(combis, parseCombiData(memberPair))
|
||||
}
|
||||
|
||||
// Create a map from string to CombiLine
|
||||
@ -188,11 +172,10 @@ func main() {
|
||||
// Convert each CombiData into a CombiRoute and store it
|
||||
for _, combi := range combis {
|
||||
log.Printf("Processing %s %s", combi.Company, combi.Ref)
|
||||
returnCoord := make([][]float64, 0)
|
||||
combiRoute := CombiRoute{
|
||||
Name: combi.Ref,
|
||||
Departure: getCoordinates(&osmDocument.Ways, nodesMap, combi.Members),
|
||||
Return: &returnCoord,
|
||||
Return: getCoordinates(&osmDocument.Ways, nodesMap, combi.ReturnMembers),
|
||||
}
|
||||
combiLineSlice := combiRoutesMap[combi.Id]
|
||||
combiLineSlice.Routes = append(combiLineSlice.Routes, combiRoute)
|
||||
@ -348,6 +331,10 @@ func writeOutput(lines map[string]*CombiLine, routes map[int]*CombiRouteContaine
|
||||
for _, combiLine := range lines {
|
||||
combiLineSlice = append(combiLineSlice, combiLine)
|
||||
}
|
||||
// sort the map
|
||||
sort.Slice(combiLineSlice, func(i, j int) bool {
|
||||
return combiLineSlice[i].Id < combiLineSlice[j].Id
|
||||
})
|
||||
|
||||
// print JSON
|
||||
jsonBytes, err := json.Marshal(combiLineSlice)
|
||||
@ -361,6 +348,9 @@ func writeOutput(lines map[string]*CombiLine, routes map[int]*CombiRouteContaine
|
||||
//
|
||||
for lineId, routeContainer := range routes {
|
||||
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)
|
||||
if err != nil {
|
||||
panic(nil)
|
||||
@ -375,7 +365,10 @@ func writeOutput(lines map[string]*CombiLine, routes map[int]*CombiRouteContaine
|
||||
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 nameTag *OsmTag
|
||||
var refTag *OsmTag
|
||||
@ -420,9 +413,101 @@ func parseCombiData(member OsmRelation) CombiData {
|
||||
Ref: refTag.V,
|
||||
Color: colorTag.V,
|
||||
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.
|
||||
// E.g.: "C11 - Cotum" -> 11
|
||||
func parseLineId(lineName string) int {
|
||||
|
Loading…
Reference in New Issue
Block a user