package api import ( "encoding/json" "fmt" "log" "net/http" "os" "sort" "strings" "time" "github.com/gin-gonic/gin" ) type IDFMLine struct { DatasetID string `json:"datasetid"` RecordIDs string `json:"recordid"` Fields struct { IdLine string `json:"id_line"` Name string `json:"name_line"` ShortName string `json:"shortname_line"` TransportMode string `json:"transportmode"` TransportSubmode string `json:"transportsubmode"` Type string `json:"type"` OperatorRef string `json:"operatorref"` AdditionalOperators string `json:"additionaloperators,omitempty"` OperatorName string `json:"operatorname"` NetworkName string `json:"networkname,omitempty"` WebColor string `json:"colourweb_hexa"` PrintColor string `json:"colourprint_cmjn"` WebTextColor string `json:"textcolourweb_hexa"` TextPrintColor string `json:"textcolourprint_hexa"` Accessibility string `json:"accessibility"` AudibleSignAvailable string `json:"audiblesigns_available"` VisualSignAvailable string `json:"visualsigns_available"` NoticeTitle string `json:"notice_title"` NoticeText string `json:"notice_text"` Status string `json:"status"` ShortNameGroup string `json:"shortname_groupoflines"` IdGroup string `json:"id_groupoflines"` ExternalCode string `json:"externalcode_line"` } `json:"fields"` RecordTimestamp time.Time `json:"record_timestamp"` } type PGLine struct { Code string `json:"code"` Name string `json:"name"` Directions string `json:"directions"` Id string `json:"id"` } type ByName []PGLine func (s ByName) Len() int { return len(s) } func (s ByName) Less(i, j int) bool { return strings.Compare(s[i].Id, s[j].Id) <= 0 } func (s ByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } var IDFMLines []IDFMLine func init() { fd, err := os.Open("referentiel-des-lignes.json") if err != nil { log.Fatal("Unable to open `referentiel-des-lignes.json`:", err.Error()) } defer fd.Close() dec := json.NewDecoder(fd) if err = dec.Decode(&IDFMLines); err != nil { log.Fatal("Unable to decode `referentiel-des-lignes.json`:", err.Error()) } } func convertLineType(old string) string { switch old { case "buses": return "bus" case "metros": return "metro" case "noctiliens": return "noctilien" case "rers": return "rail" case "tramways": return "tram" default: return old } } func convertCode(t, code string) string { if !strings.HasPrefix(code, "line:IDFM:") { if t == "tram" && !strings.HasPrefix(code, "T") { code = "T" + code } if t == "noctilien" && !strings.HasPrefix(code, "N") { code = "N" + code } if len(code) != 6 || !strings.HasPrefix(code, "C") { code = searchLine(t, code) } code = "line:IDFM:" + code } return code } func searchLine(t, code string) string { for _, line := range IDFMLines { if line.Fields.ShortName == code && (line.Fields.TransportMode == t || strings.ToLower(line.Fields.NetworkName) == t) { return line.Fields.IdLine } } return code } func declareLinesRoutes(router *gin.RouterGroup) { router.GET("/lines", func(c *gin.Context) { var modes []string for _, line := range IDFMLines { mode := line.Fields.TransportMode found := false for _, m := range modes { if mode == m { found = true break } } if !found { modes = append(modes, mode) } } c.JSON(http.StatusOK, APIResult(c, modes)) }) router.GET("/lines/:type", func(c *gin.Context) { t := convertLineType(string(c.Param("type"))) var lines []PGLine for _, line := range IDFMLines { if line.Fields.TransportMode == t || strings.ToLower(line.Fields.NetworkName) == t { name := line.Fields.Name if line.Fields.ShortNameGroup != "" { if strings.Contains(line.Fields.ShortNameGroup, name) { name = line.Fields.ShortNameGroup } else if name == line.Fields.ShortName { name = fmt.Sprintf("%s - %s", line.Fields.Name, line.Fields.ShortNameGroup) } } pgline := PGLine{ Code: line.Fields.ShortName, Name: name, Directions: "", Id: fmt.Sprintf("STIF:Line::%s:", line.Fields.IdLine), } lines = append(lines, pgline) } } sort.Sort(ByName(lines)) c.JSON(http.StatusOK, APIResult(c, map[string][]PGLine{ string(c.Param("type")): lines, })) }) }