-
Notifications
You must be signed in to change notification settings - Fork 0
/
dataView.go
135 lines (117 loc) · 3.89 KB
/
dataView.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package durcov
import (
"fmt"
"github.com/jackc/pgx"
"gopkg.in/errgo.v2/fmt/errors"
)
// Datum represents a datapoint
type Datum int
// Representst covid related datapoints
const (
Confirmed Datum = iota + 1
Deaths
Recovered
Active
)
// DataView describes functions for obtaining view data
type DataView interface {
SetDBConnection(pgxpool *pgx.ConnPool)
LatestGlobalView(datapoint Datum) (int64, error)
LatestCountryView(countryCode string, datapoint Datum) (name string, count int64, err error)
}
// NoCountryMatchedError when data for a given country code is not found in the database
type NoCountryMatchedError struct {
attemptedCode string
}
func (n *NoCountryMatchedError) Error() string {
errMsg := fmt.Sprintf("No country matched with code %s", n.attemptedCode)
return errMsg
}
// CovidBotView represents a view for covid data
type CovidBotView struct {
pgxpool *pgx.ConnPool
}
// SetDBConnection sets a database connectioon to be used to generate view data.
// Must be set before trying to generate views.
func (c *CovidBotView) SetDBConnection(pool *pgx.ConnPool) {
c.pgxpool = pool
}
// LatestGlobalView returns the latest (available) global data for the given datapoint
// Returns error if the given datapoint does not have a view implemented.
func (c *CovidBotView) LatestGlobalView(datapoint Datum) (int64, error) {
if c.pgxpool == nil {
return 0, errors.New("DB Connection not set in data view")
}
switch datapoint {
case Active:
return c.latestGlobalActive()
case Deaths:
return c.latestGlobalDeaths()
default:
return 0, errors.Newf("Unsupported Op for Global View. Datum Enum %d", datapoint)
}
}
func (c *CovidBotView) latestGlobalActive() (int64, error) {
var confirmed int64
var deaths int64
var recovered int64
err := c.pgxpool.QueryRow("SELECT confirmed, deaths, recovered FROM covid_stats WHERE id='GLOBAL';").Scan(&confirmed, &deaths, &recovered)
if err != nil {
return 0, err
}
globalActive := calculateActive(confirmed, deaths, recovered)
return globalActive, nil
}
func (c *CovidBotView) latestGlobalDeaths() (int64, error) {
var deaths int64
err := c.pgxpool.QueryRow("SELECT deaths FROM covid_stats WHERE id='GLOBAL';").Scan(&deaths)
if err != nil {
return 0, err
}
return deaths, nil
}
// LatestCountryView returns the latest (available) covid data for the given country code and datapoint.
// Returns err if no match found for the country code (or) if no view implemented for the datapoint.
func (c *CovidBotView) LatestCountryView(countryCode string, datapoint Datum) (string, int64, error) {
if c.pgxpool == nil {
return "", 0, errors.New("DB Connection not set in data view")
}
switch datapoint {
case Active:
return c.latestCountryActive(countryCode)
case Deaths:
return c.latestCountryDeaths(countryCode)
default:
return "", 0, errors.Newf("Unsupported Op for Country View. Datum Enum %d", datapoint)
}
}
func (c *CovidBotView) latestCountryActive(countryCode string) (string, int64, error) {
var confirmed int64
var deaths int64
var recovered int64
var name string
err := c.pgxpool.QueryRow("SELECT name, confirmed, deaths, recovered FROM covid_stats WHERE id=$1;", countryCode).Scan(&name, &confirmed, &deaths, &recovered)
if err != nil {
if err == pgx.ErrNoRows {
return "", 0, &NoCountryMatchedError{countryCode}
}
return "", 0, err
}
countryActive := calculateActive(confirmed, deaths, recovered)
return name, countryActive, nil
}
func (c *CovidBotView) latestCountryDeaths(countryCode string) (string, int64, error) {
var deaths int64
var name string
err := c.pgxpool.QueryRow("SELECT name, deaths FROM covid_stats WHERE id=$1;", countryCode).Scan(&name, &deaths)
if err != nil {
if err == pgx.ErrNoRows {
return "", 0, &NoCountryMatchedError{countryCode}
}
return "", 0, err
}
return name, deaths, nil
}
func calculateActive(confirmed int64, deaths int64, recovered int64) int64 {
return confirmed - (deaths + recovered)
}