Skip to content
This repository has been archived by the owner on Jan 29, 2023. It is now read-only.

We need to create a parameter to filter by states #3

Open
renanbastos93 opened this issue Mar 28, 2020 · 8 comments
Open

We need to create a parameter to filter by states #3

renanbastos93 opened this issue Mar 28, 2020 · 8 comments
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed

Comments

@renanbastos93
Copy link
Owner

We need to improve this application to create some filters I suggested we create a filter by states but we can create also filter by cities and countries.

@renanbastos93 renanbastos93 added enhancement New feature or request help wanted Extra attention is needed good first issue Good for newcomers labels Mar 28, 2020
@natea123
Copy link

New to open-source contribution but would like to take a crack at this.

Since this is pulling from an API just showing cases in Brazil [1] would you want to just implement states/cities filter for Brazil?

[1] https://covid19-brazil-api-docs.now.sh/

@natea123
Copy link

Additionally, implementing the NovelCOVID API [1] may make filtering by country easier

[1] https://github.com/NovelCOVID/API

@renanbastos93
Copy link
Owner Author

New to open-source contribution but would like to take a crack at this.

Since this is pulling from an API just showing cases in Brazil [1] would you want to just implement states/cities filter for Brazil?

[1] https://covid19-brazil-api-docs.now.sh/

Hello, thanks for this interesting contribution here.

Well, I believe that we should create a filter for any country, state, and city. I wish this system be used by anyone.

@renanbastos93
Copy link
Owner Author

Additionally, implementing the NovelCOVID API [1] may make filtering by country easier

[1] https://github.com/NovelCOVID/API

How nice, project it is interesting I will see.
we can use this API too.

@natea123
Copy link

Working on adding the new API to the application with minimal change but running into error

json: cannot unmarshal array into Go value of type struct { Data main.LastValues "json:"data"" }

Below is my current implementation, running into issues unmarshaling the data, any insight would be appreciated:

package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/gen2brain/beeep"
)

// Exported ...
const (
	IMG string = "https://static.poder360.com.br/2020/03/23312-868x644.png"
	URL        = "https://corona.lmao.ninja/countries?sort=country"
)

// LastValues ...
type LastValues struct {
	Confirmed int `json:"cases"`
	Deaths    int `json:"deaths"`
	Recovered int `json:"recovered"`
}

func (l LastValues) String() string {
	return fmt.Sprintf("Confirmed: %d, Deaths: %d, Recovered: %d", l.Confirmed, l.Deaths, l.Recovered)
}

// fetchCOVID19Data ...
func fetchCOVID19Data(ctx context.Context, req *http.Request) <-chan LastValues {
	ch := make(chan LastValues)
	go func() {
		var r struct {
			Data LastValues `json:"data"`
		}
		body, err := http.DefaultClient.Do(req)
		if err != nil {
			log.Printf("fetchCOVID19Data: %v", err)
			return
		}
		defer body.Body.Close()
		err = json.NewDecoder(body.Body).Decode(&r)
		if err != nil {
			log.Printf("fetchCOVID19Data: %v", err)
			return
		}

		select {
		case ch <- LastValues{r.Data.Confirmed, r.Data.Deaths, r.Data.Recovered}:
		case <-ctx.Done():
		}
	}()
	return ch
}

func routine(sleep time.Duration) {
	cachedVal := LastValues{}
	const timeout = time.Second * 2
	for {
		ctx, cancel := context.WithTimeout(context.Background(), timeout)
		req, err := http.NewRequestWithContext(ctx, "GET", URL, nil)
		if err != nil {
			panic("internal error - misuse of NewRequestWithContext")
		}
		select {
		case newVal := <-fetchCOVID19Data(ctx, req):
			if cachedVal != newVal {
				err := beeep.Alert("COVID-19 Brazil", newVal.String(), IMG)
				if err != nil {
					log.Printf("rountine: %v", err)
				}
				cachedVal = newVal
			}
		case <-ctx.Done():
			log.Printf("rountine: %v", ctx.Err())
		}
		cancel()
		log.Printf("sleeping for %s", sleep)
		time.Sleep(sleep)
	}
}

func main() {
	log.SetPrefix(os.Args[0] + ": ")
	log.SetFlags(0)
	var timer time.Duration
	flag.DurationVar(&timer, "t", time.Hour, "interval between each api request")
	flag.Parse()
	routine(timer)
}

@natea123
Copy link

Below is how im unmarshaling in my current working implementation of the API:

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
)

func main() {

	var country string

	flag.StringVar(&country, "country", "", "specify country for COVID case stats")
	flag.Parse()

	type Resp struct {
		Country   string
		Cases     int
		Deaths    int
		Recovered int
	}

	url := "https://corona.lmao.ninja/countries?sort=country"
	method := "GET"

	client := &http.Client{}
	req, err := http.NewRequest(method, url, nil)

	if err != nil {
		fmt.Println(err)
	}
	res, err := client.Do(req)
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)

	var resp []Resp
	json.Unmarshal([]byte(body), &resp)
}

@renanbastos93
Copy link
Owner Author

Working on adding the new API to the application with minimal change but running into error

json: cannot unmarshal array into Go value of type struct { Data main.LastValues "json:"data"" }

Below is my current implementation, running into issues unmarshaling the data, any insight would be appreciated:

package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/gen2brain/beeep"
)

// Exported ...
const (
	IMG string = "https://static.poder360.com.br/2020/03/23312-868x644.png"
	URL        = "https://corona.lmao.ninja/countries?sort=country"
)

// LastValues ...
type LastValues struct {
	Confirmed int `json:"cases"`
	Deaths    int `json:"deaths"`
	Recovered int `json:"recovered"`
}

func (l LastValues) String() string {
	return fmt.Sprintf("Confirmed: %d, Deaths: %d, Recovered: %d", l.Confirmed, l.Deaths, l.Recovered)
}

// fetchCOVID19Data ...
func fetchCOVID19Data(ctx context.Context, req *http.Request) <-chan LastValues {
	ch := make(chan LastValues)
	go func() {
		var r struct {
			Data LastValues `json:"data"`
		}
		body, err := http.DefaultClient.Do(req)
		if err != nil {
			log.Printf("fetchCOVID19Data: %v", err)
			return
		}
		defer body.Body.Close()
		err = json.NewDecoder(body.Body).Decode(&r)
		if err != nil {
			log.Printf("fetchCOVID19Data: %v", err)
			return
		}

		select {
		case ch <- LastValues{r.Data.Confirmed, r.Data.Deaths, r.Data.Recovered}:
		case <-ctx.Done():
		}
	}()
	return ch
}

func routine(sleep time.Duration) {
	cachedVal := LastValues{}
	const timeout = time.Second * 2
	for {
		ctx, cancel := context.WithTimeout(context.Background(), timeout)
		req, err := http.NewRequestWithContext(ctx, "GET", URL, nil)
		if err != nil {
			panic("internal error - misuse of NewRequestWithContext")
		}
		select {
		case newVal := <-fetchCOVID19Data(ctx, req):
			if cachedVal != newVal {
				err := beeep.Alert("COVID-19 Brazil", newVal.String(), IMG)
				if err != nil {
					log.Printf("rountine: %v", err)
				}
				cachedVal = newVal
			}
		case <-ctx.Done():
			log.Printf("rountine: %v", ctx.Err())
		}
		cancel()
		log.Printf("sleeping for %s", sleep)
		time.Sleep(sleep)
	}
}

func main() {
	log.SetPrefix(os.Args[0] + ": ")
	log.SetFlags(0)
	var timer time.Duration
	flag.DurationVar(&timer, "t", time.Hour, "interval between each api request")
	flag.Parse()
	routine(timer)
}

Hello, I am sorry for you to wait,

Well, this error occurrent because the JSON in the body is not matched with struct LastValues then we need to change struct to another approach. According to your another example in comment #3 (comment)

Like this:

type LastValue struct {
	Country   string `json:"country"`
	Cases     int 	 `json:"cases"`
	Deaths    int    `json:"deaths"`
	Recovered int    `json:"recovered"`
}

@renanbastos93
Copy link
Owner Author

Both examples sound good. So I suggest we create the filter that compares country case is different to Brazil use Novel API else use currently API when to use Novel we can get geolocation from client to get country based this.

@natea123 What do you think?

@renanbastos93 renanbastos93 linked a pull request Apr 12, 2020 that will close this issue
@renanbastos93 renanbastos93 removed a link to a pull request Apr 12, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants