From 0653c3181444c2c52ece5470b136be52cd5655b2 Mon Sep 17 00:00:00 2001
From: Mathilde Hertaas <maimh@stud.ntnu.no>
Date: Wed, 5 Mar 2025 18:49:56 +0100
Subject: [PATCH] pupolation info is implemented with correct year limit

---
 README.md                      |  33 +++++--
 handelers/populasjonhandler.go | 168 ++++++++++++++++++++++++++++++++-
 main.go                        |   1 +
 main/main.go                   |  26 -----
 4 files changed, 191 insertions(+), 37 deletions(-)
 delete mode 100644 main/main.go

diff --git a/README.md b/README.md
index 62922b5..2a66c7b 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,13 @@
-# Cloud Project
+### Assignment 1
 
+## Kjøre koden
+koden kjøres ved å skrive go run main.go i temrinalen
+    - Da blir du eventuelt automatisk sendt til
+            http://localhost:8080/
+                Dette er Hjemmeside
+    - Eventuelt kan du bruke fremgangsmåtene under Endepunkter for å navigere applikajsonen
 
-# Endepunkter
-    1. Hente informasjon om et land basert på  en 2-letter country codes (ISO 3166-2).
-        * Endpoint: /countryinfo/v1/info/{country_code}{?limit=10}
-        * Metode: GET
-        * Eksempel: http://localhost:8080/countryinfo/v1/info/NO
-
-
-# Hjemmeside (/)
+## Hjemmeside (/)
 Når du åpner API-et uten spesifikke forespørsler (http://localhost:8080/), 
 vil du bli sendt til en JSON-side med informasjon om hvordan du bruker API-et.
 
@@ -17,4 +16,18 @@ Her får du informasjon om de tre endepunktene som er tilgjengelige:
     2. populasjon
     3. status
 Du får også se hvordan riktig format av url forespørsel til en av disse endepunktene
-vil se ut og eksempler på riktig bruk.
\ No newline at end of file
+vil se ut og eksempler på riktig bruk.
+
+
+## Endepunkter
+#info
+    1. Hente informasjon om et land basert på en 2-letter country codes (ISO 3166-2).
+        * Endpoint: /countryinfo/v1/info/{country_code}{?limit=10}
+        * Metode: GET
+        * Eksempel: http://localhost:8080/countryinfo/v1/info/NO?limit=4
+#populasjon
+    2. Hente populasjonsdata
+    GET http://localhost:8080/population/NO
+    GET http://localhost:8080/population/NO?limit=2010-2015
+
+
diff --git a/handelers/populasjonhandler.go b/handelers/populasjonhandler.go
index bb27ce5..b81780c 100644
--- a/handelers/populasjonhandler.go
+++ b/handelers/populasjonhandler.go
@@ -1 +1,167 @@
-package handelers
\ No newline at end of file
+package handelers
+
+import (
+	"encoding/json"
+	"fmt"
+	"math"
+	"net/http"
+	"strconv"
+	"strings"
+)
+
+// responsstruktur for befolkningsdata
+type PopulationResponse struct {
+	Error bool     `json:"error"`
+	Msg   string   `json:"msg"`
+	Data  []Country `json:"data"`
+}
+
+// land og dens befolkningsdata
+type Country struct {
+	Name             string            `json:"country"`
+	Code             string            `json:"iso3"` // Trebokstavskode (ISO 3166-1 alpha-3)
+	PopulationCounts []PopulationCount `json:"populationCounts"`
+}
+
+
+
+
+// befolkningsdate for et bestemt år (brukes i den endelige repsonsen under values)
+type PopulationCount struct {
+	Year  int `json:"year"`
+	Value int `json:"value"`
+}
+
+// Responsstruktur for vårt API(det som vises på skjerm)
+type PopulationAPIResponse struct {
+	Name           string            `json:"land"`
+	Gjennomsnitt   int               `json:"gjennomsnittlig populasjon"`
+	Values        []PopulationCount  `json:"årlige populasjoner"`
+}
+
+
+
+
+
+
+
+// ISO 3166-1 alpha-2 til alpha-3 landkoder
+var isoAlpha2ToAlpha3 = make(map[string]string)
+
+// Henter befolkningsdata fra eksternt API
+func fetchPopulationData() (*PopulationResponse, error) {
+	url := "https://countriesnow.space/api/v0.1/countries/population"
+	resp, err := http.Get(url)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+
+	var data PopulationResponse
+	err = json.NewDecoder(resp.Body).Decode(&data)
+	if err != nil {
+		return nil, err
+	}
+
+	// Bygg dynamisk oppslagskart for landkoder
+	for _, country := range data.Data {
+		if len(country.Code) >= 2 {
+			isoAlpha2ToAlpha3[strings.ToUpper(country.Code[:2])] = country.Code // F.eks. NO → NOR
+		}
+	}
+
+	return &data, nil
+}
+
+// Henter befolkningsdata for et spesifikt land og filtrerer etter år
+func getPopulationForCountry(alpha2Code string, startYear, endYear int) (*PopulationAPIResponse, error) {
+	data, err := fetchPopulationData()
+	if err != nil {
+		return nil, err
+	}
+
+	// Konverter ISO 3166-1 alpha-2 til alpha-3
+	alpha3Code, exists := isoAlpha2ToAlpha3[strings.ToUpper(alpha2Code)]
+	if !exists {
+		return nil, fmt.Errorf("invalid country code: %s", alpha2Code)
+	}
+
+	// Finn landet basert på ISO 3166-1 alpha-3 kode
+	var countryData *Country
+	for _, c := range data.Data {
+		if c.Code == alpha3Code {
+			countryData = &c
+			break
+		}
+	}
+
+	if countryData == nil {
+		return nil, fmt.Errorf("country not found")
+	}
+
+	// Filtrer basert på år
+
+	// en tom liste fyllt med PopulationCount, altså fylles med spesifikke år og antall
+	var filteredValues []PopulationCount
+	var total int
+	count := 0
+
+	// itererer over alle verdiene som følger med et land sin populasjonsdata
+		// over alle årstall-verdi strukturene
+	for _, stk := range countryData.PopulationCounts {
+		if (startYear == 0 || stk.Year >= startYear) && (endYear == 0 || stk.Year <= endYear) {
+			filteredValues = append(filteredValues, stk)
+			total += stk.Value
+			count++
+		}
+	}
+
+	// Beregn gjennomsnitt
+	mean := 0
+	if count > 0 {
+		mean = int(math.Round(float64(total) / float64(count)))
+	}
+
+	return &PopulationAPIResponse{
+		Name:         countryData.Name,
+		Gjennomsnitt: mean,
+		Values:       filteredValues,
+	}, nil
+}
+
+
+
+
+func PopulationHandler(w http.ResponseWriter, r *http.Request) {
+	// r.URL.Path er den fulle URL som ble sendt til serveren altså /population/NO
+	// deretter fjerner den /population/ så vi sitter igjen med NO
+    path := strings.TrimPrefix(r.URL.Path, "/population/")
+			// NO
+	countryCode := strings.ToUpper(path) // ISO 3166-2-kode
+
+
+	query := r.URL.RawQuery
+	limit := strings.Replace(query, "limit=","",1)
+
+
+    startYear, endYear := 0, 0
+
+    if len(limit)>0 {
+        yearRange := strings.Split(limit, "-")
+        if len(yearRange) == 2 {
+            startYear, _ = strconv.Atoi(yearRange[0])
+            endYear, _ = strconv.Atoi(yearRange[1])
+        } else {
+            fmt.Println("Year range format is incorrect")
+        }
+    }
+
+    result, err := getPopulationForCountry(countryCode, startYear, endYear)
+    if err != nil {
+        http.Error(w, err.Error(), http.StatusNotFound)
+        return
+    }
+
+    w.Header().Set("Content-Type", "application/json")
+    json.NewEncoder(w).Encode(result)
+}
\ No newline at end of file
diff --git a/main.go b/main.go
index 90fff95..ee53077 100644
--- a/main.go
+++ b/main.go
@@ -18,6 +18,7 @@ func main() {
 	})
 	http.HandleFunc("/", handelers.HomeHandler)
 	http.HandleFunc("/countryinfo/v1/info/", handelers.CountryInfoHandler)
+	http.HandleFunc("/population/", handelers.PopulationHandler)
 
 
 	fmt.Println("Server running on port 8080...")
diff --git a/main/main.go b/main/main.go
deleted file mode 100644
index 9501725..0000000
--- a/main/main.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package main
-
-import (
-	"fmt"
-	"net/http"
-	"time"
-	"git.gvk.idi.ntnu.no/Mathilde/cloud/handelers"
-)
-
-var serviceStartTime time.Time
-
-func main() {
-	serviceStartTime = time.Now()
-
-	// Send serviceStartTime til DiagnosticsHandler
-	http.HandleFunc("/status/", func(w http.ResponseWriter, r *http.Request) {
-		handelers.DiagnosticsHandler(w, r, serviceStartTime)
-	})
-	http.HandleFunc("/", handelers.HomeHandler)
-	http.HandleFunc("/countryinfo/v1/info/", handelers.CountryInfoHandler)
-
-	fmt.Println("Server running on port 8080...")
-	if err := http.ListenAndServe(":8080", nil); err != nil {
-		fmt.Printf("Server failed to start: %s\n", err)
-	}
-}
\ No newline at end of file
-- 
GitLab