package universities import ( "context" "fmt" "slices" "strings" "sync" "git.bissendorf.co/bissendorf/unifood/m/v2/core/interfaces" "git.bissendorf.co/bissendorf/unifood/m/v2/core/interfaces/params" "git.bissendorf.co/bissendorf/unifood/m/v2/model/external/stwbremen" "git.bissendorf.co/bissendorf/unifood/m/v2/model/resources" "git.bissendorf.co/bissendorf/unifood/m/v2/util" ) type RestaurantHandler struct { QueryClient interfaces.QueryClient[stwbremen.RestaurantList] QueryClientRestaurant interfaces.QueryClient[stwbremen.Restaurant] } func (h *RestaurantHandler) Get(ctx context.Context, name string, params params.Container) (*interfaces.ResourceList, error) { var list []string = []string{name} // If no name provided, get list of all available restaurants if name == "" { fetchedNames, err := getRestaurantList(ctx, h.QueryClient) if err != nil { return nil, err } list = fetchedNames } // Get restaurant information in parallel var wg sync.WaitGroup var mutex sync.Mutex restaurants := make([]resources.Restaurant, 0, len(list)) for _, name := range list { wg.Add(1) go func() { defer wg.Done() restaurant, err := h.getRestaurantInfo(ctx, name) // Append restaurant in critical section if err == nil { mutex.Lock() restaurants = append(restaurants, *restaurant) mutex.Unlock() } }() } wg.Wait() // Sort by name slices.SortFunc(restaurants, func(a, b resources.Restaurant) int { return strings.Compare(a.Name, b.Name) }) // Return return &interfaces.ResourceList{ ItemKind: resources.ResourceRestaurant, Items: util.Transform(restaurants, func(i *resources.Restaurant) interfaces.Resource { return i }), }, nil } func (h *RestaurantHandler) getRestaurantInfo(ctx context.Context, name string) (*resources.Restaurant, error) { r, err := h.QueryClientRestaurant.Get(ctx, fmt.Sprintf("page('essen-und-trinken/%s')", name), `{"title": "page.title","id": "page.content.mensalocationid","image": "page.files.first().url","address": "page.content.address","openingTimes": {"query": "page.openingTimes.toStructure()","select": {"weekday": "structureItem.day","openingTime": "structureItem.open","closingTime": "structureItem.close"}},"offseasonOpeningTimes": {"query": "page.offseasonOpeningTimes.toStructure()","select": {"weekday": "structureItem.day","openingTime": "structureItem.open","closingTime": "structureItem.close"}},"offseasonStart": true,"offseasonEnd": true,"changedTimes": {"query": "page.changedTimes.toStructure()","select": {"startDate": "structureItem.startChangedDate","endDate": "structureItem.endChangedDate","openingTime": "structureItem.openChangedTime","closingTime": "structureItem.closedChangedTime"}}}`, false, ) if err != nil { return nil, fmt.Errorf("failed to load restaurant %s: %w", name, err) } if r.Title == "" { return nil, fmt.Errorf("restaurant not found: %s", name) } return &resources.Restaurant{ Name: name, Title: r.Title, ID: r.ID, Address: r.Address, Image: r.Image, OpeningHours: r.OpeningHours, }, nil } func (h *RestaurantHandler) GetParametersForVerb(verb interfaces.Verb) []params.Registration { return []params.Registration{} }