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