package bus import ( "fmt" "sort" "strconv" "strings" query "github.com/tgckpg/golifehk/query" utils "github.com/tgckpg/golifehk/utils" ) type QueryResult struct { Schedules *map[*BusStop]*BusStopBuses Lang string Error error Query *query.QueryObject } func writeShortRoute(lang *string, sb *strings.Builder, b *BusStop) { if b.PrevStop() != nil { utils.WriteMDv2Text(sb, (*b.PrevStop().Name)[*lang]) sb.WriteString(" \\> ") } sb.WriteString("*") utils.WriteMDv2Text(sb, (*b.Name)[*lang]) sb.WriteString("*") if b.NextStop() != nil { sb.WriteString(" \\> ") utils.WriteMDv2Text(sb, (*b.NextStop().Name)[*lang]) } sb.WriteString("\n") } func (this QueryResult) Message() (string, error) { if this.Error != nil { return "", this.Error } sb := strings.Builder{} if this.Schedules == nil { q := *this.Query if len(*q.Results) == 0 { terms := make([]string, len(*q.SearchTerms), len(*q.SearchTerms)) for i, term := range *q.SearchTerms { terms[i] = term.Org } return "", fmt.Errorf("Not Found: \"%s\"", strings.Join(terms, "\", \"")) } if q.Key == "" { sort.Sort(query.ByKey(*q.Results)) for _, entry := range *q.Results { busStop := any(entry).(*BusStop) utils.WriteMDv2Text(&sb, busStop.RouteId) sb.WriteString(" ") writeShortRoute(&this.Lang, &sb, busStop) } } else if 1 == len(*q.SearchTerms) { // Route listing busLines := map[string]map[string]*BusStop{} for _, entry := range *q.Results { busStop := any(entry).(*BusStop) busRoutes := busLines[busStop.ReferenceId] if busRoutes == nil { busRoutes = make(map[string]*BusStop) busLines[busStop.ReferenceId] = busRoutes } if _, ok := busRoutes[busStop.Direction]; ok { continue } busRoutes[busStop.Direction] = busStop for busRoutes[busStop.Direction].PrevStop() != nil { busRoutes[busStop.Direction] = busRoutes[busStop.Direction].PrevStop() } } // Sort Bus Lines lineKeys := make([]string, 0, len(busLines)) for k := range busLines { lineKeys = append(lineKeys, k) } sort.Slice(lineKeys, func(i, j int) bool { ai, an := splitKey(lineKeys[i]) bi, bn := splitKey(lineKeys[j]) // different base → normal string compare if ai != bi { return ai < bi } // same base: base key comes first if an == -1 && bn != -1 { return true } if an != -1 && bn == -1 { return false } // both have suffix → numeric compare return an < bn }) for _, lineKey := range lineKeys { busRoutes := busLines[lineKey] // Sort route directions dirKeys := make([]string, 0, len(busRoutes)) for k := range busRoutes { dirKeys = append(dirKeys, k) } sort.Strings(dirKeys) for _, d := range dirKeys { b := busRoutes[d] utils.WriteMDv2Text(&sb, lineKey) if d == "O" { sb.WriteString("↑") } else if d == "I" { sb.WriteString("↓") } else { sb.WriteString("\\?") } sb.WriteString("\n ") for { utils.WriteMDv2Text(&sb, (*b.Name)[this.Lang]) b = b.NextStop() if b == nil { break } sb.WriteString(" \\> ") } sb.WriteString("\n") } } } else { return "", fmt.Errorf("%s", "Unreachable condition occured!?") } } else { if 0 < len(*this.Schedules) { busStops := []*BusStop{} for b, _ := range *this.Schedules { busStops = append(busStops, b) } sort.Sort(ByRoute(busStops)) for _, busStop := range busStops { buses := (*this.Schedules)[busStop] writeShortRoute(&this.Lang, &sb, busStop) for _, bus := range buses.Buses { sb.WriteString(" \\* ") if bus.ETAText == "" { utils.WriteMDv2Text(&sb, bus.ETDText) } else { utils.WriteMDv2Text(&sb, bus.ETAText) } sb.WriteString("\n") } sb.WriteString("\n") } } else { utils.WriteMDv2Text(&sb, "Schedules are empty...perhaps Out of Service Time?") } } return sb.String(), nil } func splitKey(s string) (base string, num int) { parts := strings.SplitN(s, "-", 2) if len(parts) == 1 { return s, -1 // base key, no suffix } n, err := strconv.Atoi(parts[1]) if err != nil { return s, -1 // fallback: treat as base } return parts[0], n }