Commit Diff


commit - /dev/null
commit + e281b487dc74e5bfbeaf8c45995d2462f524ad4a
blob - /dev/null
blob + 948e872bf0176fe3c7612306144ff7d8c5e58df0 (mode 644)
--- /dev/null
+++ README.md
@@ -0,0 +1,16 @@
+# cli_incidence
+
+cli_incidence talks to the RKI (Robert-Koch-Institut) REST API and posts the incidence of the specified districts to STDOUT.
+
+# Requirements
+
+- The Go compiler
+
+# Compiling
+
+`go build main.go`
+
+# Running
+
+`./main -d "12062,hildburghausen"`
+
blob - /dev/null
blob + e84132b76dc908f10577509cf293acc5b9ade142 (mode 644)
--- /dev/null
+++ main.go
@@ -0,0 +1,121 @@
+package main
+
+import (
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"strings"
+
+	"github.com/spf13/pflag"
+)
+
+// will be set after parsing commandline arguments
+var ApiString string
+var DistrictApi string
+
+// direct response from the server
+type DistrictResponseData struct {
+	Data map[string]DistrictResponse `json:"data"`
+	//Meta []MetaResponse `json:"meta"`
+}
+
+// data field of the response
+type DistrictResponse struct {
+	// Allgemeiner Gemeinde Schlüssel ("ID" of the district)
+	Ags           string  `json:"ags"`
+	Name          string  `json:"name"`
+	State         string  `json:"state"`
+	County        string  `json:"county"`
+	Population    int     `json:"population"`
+	Cases         int     `json:"cases"`
+	Deaths        int     `json:"deaths"`
+	CasesPerWeek  int     `json:"casesPerWeek"`
+	DeathsPerWeek int     `json:"deathsPerWeek"`
+	Recovered     int     `json:"recovered"`
+	WeekIncidence float64 `json:"weekIncidence"`
+	CasesPer100k  float64 `json:"casesPer100k"`
+}
+
+// meta field of the response
+type MetaResponse struct {
+	Source               string `json:"source"`
+	Contact              string `json:"contact"`
+	Info                 string `json:"info"`
+	LastUpdate           string `json:"lastUpdate"`
+	LastCheckedforUpdate string `json:"lastCheckedforUpdate"`
+}
+
+func main() {
+	var apiString = pflag.StringP("api", "a", "https://api.corona-zahlen.org/", "API Endpoint to use. Ensure trailing \"/\".")
+	var district_ids = pflag.StringSliceP("districts", "d", []string{}, "Name or AGS of the districts you want to have displayed.")
+	pflag.Parse()
+
+	ApiString = *apiString
+	DistrictApi = ApiString + "districts/"
+
+	if len(*district_ids) < 1 {
+		fmt.Println("Nothing to do, no districts given. Exiting.")
+		os.Exit(0)
+	}
+
+	districts, err := getAllDistricts()
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "unable to get districts: %v\n", err)
+		return
+	}
+
+	districts.FilterDistricts(*district_ids)
+	districts.PrintIncidences()
+}
+
+func (districts *DistrictResponseData) PrintIncidences() {
+	for _, v := range districts.Data {
+		v.PrintIncidence()
+	}
+}
+
+// filters DistrictResponseData to only contain the districts specified
+// districts can be specified via their AGS or name
+func (districts *DistrictResponseData) FilterDistricts(district_ids []string) {
+loop:
+	for k, v := range districts.Data {
+		for _, id := range district_ids {
+			if v.Ags == id || strings.Contains(strings.ToLower(v.Name), strings.ToLower(id)) {
+				continue loop
+			}
+		}
+		delete(districts.Data, k)
+	}
+}
+
+func (district *DistrictResponse) PrintIncidence() {
+	fmt.Printf("%s: %.2f\n", district.Name, district.WeekIncidence)
+}
+
+func getAllDistricts() (DistrictResponseData, error) {
+	var drd DistrictResponseData
+	// initialize a (hopefully) big enough map
+	// api contains about 410 districts
+	drd.Data = make(map[string]DistrictResponse, 410)
+	apiUrl := DistrictApi
+
+	response, err := http.Get(apiUrl)
+	if err != nil {
+		return drd, err
+	}
+	defer response.Body.Close()
+
+	responseData, err := ioutil.ReadAll(response.Body)
+	if err != nil {
+		return drd, err
+	}
+
+	err = json.Unmarshal(responseData, &drd)
+	if err != nil {
+		return drd, err
+	}
+
+	return drd, nil
+}