Select Git revision
populasjonhandler.go
-
Mathilde Hertaas authoredMathilde Hertaas authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
populasjonhandler.go 4.08 KiB
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)
}