From 74d98a9fc3b928e0407bda48d997f2ab54f789de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20S=C3=A6ther?= <steffels@stud.ntnu.no> Date: Wed, 6 Mar 2024 19:47:49 +0000 Subject: [PATCH] Upload New File --- oblig1/endpoints/readership.go | 210 +++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 oblig1/endpoints/readership.go diff --git a/oblig1/endpoints/readership.go b/oblig1/endpoints/readership.go new file mode 100644 index 0000000..8f03bcc --- /dev/null +++ b/oblig1/endpoints/readership.go @@ -0,0 +1,210 @@ +package endpoints + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "strconv" + "strings" +) + +// ReadershipResponse represents the structure of the response for readership endpoint. +type ReadershipResponse struct { + Country string `json:"country"` + ISOCode string `json:"isocode"` + Books int `json:"books"` + Authors int `json:"authors"` + Readership int `json:"readership"` +} + +type Language struct { + ISO3166_1_Alpha_3 string `json:"ISO3166_1_Alpha_3"` + ISO3166_1_Alpha_2 string `json:"ISO3166_1_Alpha_2"` + Official_Name string `json:"Official_Name"` + Region_Name string `json:"Region_Name"` + Sub_Region_Name string `json:"Sub_Region_Name"` + Language string `json:"Language"` +} +type Country struct { + Population int `json:"population"` +} + +// ReadershipHandler handles requests to the /librarystats/v1/readership/ endpoint. +func ReadershipHandler(w http.ResponseWriter, r *http.Request) { + language := r.URL.Path[len("/librarystats/v1/readership/"):] + limit, err := strconv.Atoi(r.URL.Query().Get("limit")) + // Check if the string ends with "/" + if strings.HasSuffix(language, "/") { + // Remove the last character from the string + language = language[:len(language)-1] + } + // Check if the language is empty. + if err != nil { + limit = -1 + } + // Query Language2Countries API to get countries where the language is spoken. + language2CountriesAPIURL := fmt.Sprintf("http://129.241.150.113:3000/language2countries/%v", language) + req, err := http.NewRequest("GET", language2CountriesAPIURL, nil) + if err != nil { + http.Error(w, "Failed to create a new request", http.StatusInternalServerError) + return + } + req.Header.Add("Content-Type", "application/json") + client := &http.Client{} + + res, err := client.Do(req) + if err != nil { + http.Error(w, "Failed to send a request to Gutendex API", http.StatusInternalServerError) + return + } + defer res.Body.Close() + // Decode the response. + body, err := io.ReadAll(res.Body) + if err != nil { + http.Error(w, "Failed to read Gutendex API response", http.StatusInternalServerError) + return + } + var languageRes []Language + err = json.Unmarshal(body, &languageRes) + if err != nil { + http.Error(w, "Failed to decode Gutendex API response", http.StatusInternalServerError) + return + } + + // Placeholder value for total readership. + var totalReadership int + countryArray := []ReadershipResponse{} + // Calculate potential readership based on population information from REST Countries API. + for _, lang := range languageRes { + + // Assuming the language code is present in the response. + countryCode := lang.ISO3166_1_Alpha_2 + // Query REST Countries API to get population information for each country. + restCountriesAPIURL := fmt.Sprintf("http://129.241.150.113:8080/v3.1/alpha/%v", countryCode) + req, err := http.NewRequest("GET", restCountriesAPIURL, nil) + if err != nil { + http.Error(w, "Failed to create a new request", http.StatusInternalServerError) + return + } + req.Header.Add("Content-Type", "application/json") + + client := &http.Client{} + + res, err := client.Do(req) + if err != nil { + http.Error(w, "Failed to send a request to Gutendex API", http.StatusInternalServerError) + return + } + defer res.Body.Close() + + // Decode the response. + body, err := io.ReadAll(res.Body) + if err != nil { + http.Error(w, "Failed to read Gutendex API response", http.StatusInternalServerError) + return + } + + var country []Country + err = json.Unmarshal(body, &country) + if err != nil { + http.Error(w, "Failed to decode Gutendex API response", http.StatusInternalServerError) + return + } + // Assuming the population field exists in the response. + population := country[0].Population + totalReadership = population + + books, authors := GetBooksAndAuthors(countryCode) + + if lang.ISO3166_1_Alpha_2 == strings.ToUpper(language) { + mainC := ReadershipResponse{Country: lang.Official_Name, // Replace with actual country name. + ISOCode: lang.ISO3166_1_Alpha_2, // Replace with actual ISO code. + Books: books, // Placeholder value, update accordingly. + Authors: authors, // Placeholder value, update accordingly. + Readership: totalReadership} + countryArray = append([]ReadershipResponse{mainC}, countryArray...) + continue + + } else { + // Prepare and send the response. + countryArray = append(countryArray, ReadershipResponse{ + Country: lang.Official_Name, // Replace with actual country name. + ISOCode: lang.ISO3166_1_Alpha_2, // Replace with actual ISO code. + Books: books, // Placeholder value, update accordingly. + Authors: authors, // Placeholder value, update accordingly. + Readership: totalReadership, + }) + } + + } + if limit > 0 { + sendJSONResponse(w, countryArray[:limit]) + return + } + sendJSONResponse(w, countryArray) +} + +// / GetBooksAndAuthors handles requests to the /librarystats/v1/bookcount/ endpoint. +func GetBooksAndAuthors(languages string) (int, int) { + // Placeholder values for books, authors, and total books. + var totalBooks int + var authors int + var uniqueAuthors = make(map[string]struct{}) // Use a map as a set for unique authors + + // Placeholder for the URL of the first page of results. + gutendexAPIURL := fmt.Sprintf("http://129.241.150.113:8000/books/?languages=%v", languages) + + // Fetch all pages of results. + for gutendexAPIURL != "" { + req, err := http.NewRequest("GET", gutendexAPIURL, nil) + if err != nil { + fmt.Println("Error creating request:", err) + return 0, 0 + } + req.Header.Add("Content-Type", "application/json") + + client := &http.Client{} + + res, err := client.Do(req) + if err != nil { + fmt.Println("Error sending request:", err) + return 0, 0 + } + defer res.Body.Close() + + // Check the HTTP status code. + if res.StatusCode != http.StatusOK { + fmt.Println("Non-OK status code:", res.StatusCode) + return 0, 0 + } + + // Decode the response. + body, err := io.ReadAll(res.Body) + if err != nil { + fmt.Println("Error reading response:", err) + return 0, 0 + } + + var books Books + err = json.Unmarshal(body, &books) + if err != nil { + fmt.Println("Error decoding response:", err) + return 0, 0 + } + + // Increment total books and unique authors for each language. + totalBooks += books.Count + for _, book := range books.Results { + for _, author := range book.Authors { + uniqueAuthors[author.Name] = struct{}{} + } + } + + // Update the URL to the next page of results. + gutendexAPIURL = books.Next + } + + authors = len(uniqueAuthors) + return totalBooks, authors +} -- GitLab