package bus import ( "errors" "fmt" "strings" "github.com/tgckpg/golifehk/utils" ) type queryObj struct { Route string BusStops *[]BusStop Search string } type qTerm struct { Value string ProblyRoute bool } func Query( lang string, message string ) *QueryResult { qo, err := parse( message ) if err != nil { return &QueryResult{ Error: err } } if qo.Route != "" { if len( *qo.BusStops ) == 0 { return &QueryResult{ Error: errors.New( "Result not found" ) } } schedules, err := getSchedule( lang, qo.Route ) if err != nil { return &QueryResult{ Error: err } } if len( schedules.BusStops ) == 0 { return &QueryResult{ Error: errors.New( "Schedules are empty. Maybe outside service time?" ) } } matches := map[BusStop] *BusStopBuses{} for _, busStop := range *qo.BusStops { for _, busStopSch := range schedules.BusStops { if busStopSch.BusStopId == busStop.StationId { matches[busStop] = &busStopSch break } } } return &QueryResult{ Lang: lang, Schedules: &matches } } return &QueryResult{ Error: errors.New( "No Result" ) } } func test( entry BusStop, val string ) bool { switch true { case strings.Contains( strings.ToUpper( (*entry.Name)["zh"] ), val ): fallthrough case strings.Contains( strings.ToUpper( (*entry.Name)["en"] ), val ): return true } return false } func parse( line string ) ( *queryObj, error ) { busStops, err := getBusStops() if err != nil { return nil, err } var route string = "" var searches = []string{} matches := []BusStop{} // Sanitize and assume properties for each of the keywords terms := []qTerm{} for _, val := range strings.Split( line, " " ) { val = strings.ToUpper( strings.Trim( val, " " ) ) term := qTerm{ Value: val, ProblyRoute: strings.ContainsAny( val, utils.ROUTE_CHARS ), } terms = append( terms, term ) } // Search for route name first, otherwise search in other props for _, entry := range *busStops { // Search for RouteId for _, term := range terms { if term.ProblyRoute && term.Value == entry.RouteId { if route != "" && route != term.Value { return nil, fmt.Errorf( "Cannot %s & %s", route, term.Value ) } matches = append( matches, entry ) route = entry.RouteId break } searches = append( searches, term.Value ) if test( entry, term.Value ) { matches = append( matches, entry ) break } } } // If route found, filter out all other route // then search within that route if route != "" { if 0 < len( searches ) { matches_in := []BusStop{} for _, entry := range matches { if entry.RouteId != route { continue } for _, val := range searches { if test( entry, val ) { matches_in = append( matches_in, entry ) break } } } matches = matches_in } else { } } return &queryObj{ Route: route, BusStops: &matches }, err }