diff --git a/assignment1/main.go b/assignment1/main.go deleted file mode 100644 index 8704871460756aedb8a5bc17bffd583aafa35f02..0000000000000000000000000000000000000000 --- a/assignment1/main.go +++ /dev/null @@ -1,25 +0,0 @@ -package main - - -import ( - "net/http" - "assignment1/handlers" - "time" -) - -func main() { - mux := http.NewServeMux() - - mux.HandleFunc("/librarystats/v1/bookcount/", handlers.BookCountHandler) - mux.HandleFunc("/librarystats/v1/readership/", handlers.ReadershipHandler) - mux.HandleFunc("/librarystats/v1/status/", handlers.StatusHandler) - - srv := &http.Server{ - Handler: mux, - Addr: "127.0.0.1:8080", - WriteTimeout: 15 * time.Second, - ReadTimeout: 15 * time.Second, - } - - http.ListenAndServe(":8080", mux) -} diff --git a/assignment1/models/models.go b/assignment1/models/models.go deleted file mode 100644 index 05b86cdd06f113e1deb6e361408ead4cd984b8a2..0000000000000000000000000000000000000000 --- a/assignment1/models/models.go +++ /dev/null @@ -1,49 +0,0 @@ -package models - -// ... Other models - -// GutenbergBook represents the structure of a book from the Gutenberg API. -type GutenbergBook struct { - ID int `json:"id"` - Title string `json:"title"` - Authors []Person `json:"authors"` - Translators []Person `json:"translators"` - Subjects []string `json:"subjects"` - Bookshelves []string `json:"bookshelves"` - Languages []string `json:"languages"` - Copyright bool `json:"copyright"` - MediaType string `json:"media_type"` - Formats map[string]string `json:"formats"` - DownloadCount int `json:"download_count"` -} - -// GutenbergResponse represents the paginated response from Gutenberg API. -type GutenbergResponse struct { - Count int `json:"count"` - Next string `json:"next"` - Previous string `json:"previous"` - Results []GutenbergBook `json:"results"` -} - -// Person represents an author or translator. -type Person struct { - BirthYear *int `json:"birth_year"` - DeathYear *int `json:"death_year"` - Name string `json:"name"` -} - -// LanguageCountriesResponse represents the response structure from the Language2Countries API. -type LanguageCountriesResponse struct { - Countries []CountryInfo `json:"countries"` -} - -// CountryInfo represents country information in the LanguageCountriesResponse. -type CountryInfo struct { - Name string `json:"name"` - ISOCode string `json:"isoCode"` -} - -// CountryResponse represents the structure of a country response from the REST Countries API. -type CountryResponse struct { - Population int64 `json:"population"` -} diff --git a/assignment1/handlers/.gitkeep b/handlers/.gitkeep similarity index 100% rename from assignment1/handlers/.gitkeep rename to handlers/.gitkeep diff --git a/assignment1/handlers/handlers.go b/handlers/handlers.go similarity index 70% rename from assignment1/handlers/handlers.go rename to handlers/handlers.go index cd1b2e936446a4f0b966e06e8ed1b38e6a74f7c6..799450f0e7813631d8d32ef89e474a1642e85154 100644 --- a/assignment1/handlers/handlers.go +++ b/handlers/handlers.go @@ -8,6 +8,37 @@ import ( "fmt" ) +// BookCountHandler handles requests to the /librarystats/v1/bookcount/ endpoint. +func BookCountHandler(w http.ResponseWriter, r *http.Request) { + // Extract query parameters for language + query := r.URL.Query() + language := query.Get("language") + + // Fetch book data from the Gutendex API + booksResponse, err := services.FetchBooksByLanguage(language) + if err != nil { + http.Error(w, "Failed to fetch books: "+err.Error(), http.StatusInternalServerError) + return + } + + // Process the books to calculate the book count and author count + bookCount := len(booksResponse.Results) + authorCount := services.CalculateUniqueAuthors(booksResponse.Results) + + // Create a response object + response := map[string]interface{}{ + "language": language, + "bookCount": bookCount, + "authorCount": authorCount, + } + + // Write the response back as JSON + w.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(w).Encode(response); err != nil { + http.Error(w, "Failed to encode response: "+err.Error(), http.StatusInternalServerError) + } +} + func ReadershipHandler(w http.ResponseWriter, r *http.Request) { // Extract the language code from the URL path language := r.URL.Path[len("/librarystats/v1/readership/"):] diff --git a/main.go b/main.go new file mode 100644 index 0000000000000000000000000000000000000000..8564a01102c677d27048a7246c9fa3779482c8c1 --- /dev/null +++ b/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "assignment1/handlers" // Make sure this path is correct + "net/http" + "time" + "log" +) + +func main() { + mux := http.NewServeMux() + + mux.HandleFunc("/librarystats/v1/bookcount/", handlers.BookCountHandler) + mux.HandleFunc("/librarystats/v1/readership/", handlers.ReadershipHandler) + mux.HandleFunc("/librarystats/v1/status/", handlers.StatusHandler) + + srv := &http.Server{ + Handler: mux, + Addr: "127.0.0.1:8080", + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + // Use the srv variable to start the server + if err := srv.ListenAndServe(); err != nil { + log.Fatalf("Failed to start server: %v", err) + } +} diff --git a/assignment1/models/.gitkeep b/models/.gitkeep similarity index 100% rename from assignment1/models/.gitkeep rename to models/.gitkeep diff --git a/models/models.go b/models/models.go new file mode 100644 index 0000000000000000000000000000000000000000..a90be57252f6336659b20f4e37e815b4e4aa5a8e --- /dev/null +++ b/models/models.go @@ -0,0 +1,65 @@ +package models + +// GutenbergBook represents the structure of a book from the Gutenberg API. +type GutenbergBook struct { + ID int `json:"id"` + Title string `json:"title"` + Authors []Person `json:"authors"` + Translators []Person `json:"translators"` + Subjects []string `json:"subjects"` + Bookshelves []string `json:"bookshelves"` + Languages []string `json:"languages"` + Copyright bool `json:"copyright"` + MediaType string `json:"media_type"` + Formats map[string]string `json:"formats"` + DownloadCount int `json:"download_count"` +} + +// GutenbergResponse represents the paginated response from Gutenberg API. +type GutenbergResponse struct { + Count int `json:"count"` + Next string `json:"next"` + Previous string `json:"previous"` + Results []GutenbergBook `json:"results"` +} + +// Person represents an author or translator. +type Person struct { + BirthYear *int `json:"birth_year"` + DeathYear *int `json:"death_year"` + Name string `json:"name"` +} + +// LanguageCountriesResponse represents the response structure from the Language2Countries API. +type LanguageCountriesResponse struct { + Countries []CountryInfo `json:"countries"` +} + +// CountryInfo represents country information in the LanguageCountriesResponse. +type CountryInfo struct { + Name string `json:"name"` + ISOCode string `json:"isoCode"` +} + +// CountryResponse represents the structure of a country response from the REST Countries API. +type CountryResponse struct { + Population int64 `json:"population"` +} + +// ReadershipDetail represents the detailed readership information for a country. +type ReadershipDetail struct { + Country string `json:"country"` + ISOCode string `json:"isocode"` + Books int `json:"books"` + Authors int `json:"authors"` + Readership int64 `json:"readership"` +} + +// ServiceStatus represents the status of external services your application depends on. +type ServiceStatus struct { + GutendexAPI string `json:"gutendexapi"` + LanguageAPI string `json:"languageapi"` + CountriesAPI string `json:"countriesapi"` + Version string `json:"version"` + Uptime int64 `json:"uptime"` +} \ No newline at end of file diff --git a/assignment1/services/.gitkeep b/services/.gitkeep similarity index 100% rename from assignment1/services/.gitkeep rename to services/.gitkeep diff --git a/assignment1/services/services.go b/services/services.go similarity index 98% rename from assignment1/services/services.go rename to services/services.go index 1795e2d94d7eb99811f795e6ab2ea29844ee5b5f..9962bf160e80638f0036f30dffe25db79fd97fad 100644 --- a/assignment1/services/services.go +++ b/services/services.go @@ -10,8 +10,7 @@ import ( // FetchBooksByLanguage retrieves books from the Gutendex API by language. func FetchBooksByLanguage(language string) (*models.GutenbergResponse, error) { url := "http://129.241.150.113:8000/books?languages=" + language - resp, err := http.Get(url -) + resp, err := http.Get(url) if err != nil { return nil, err }