Last active
March 18, 2022 05:29
-
-
Save ostronom/84b709cef06077998509 to your computer and use it in GitHub Desktop.
gogo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"log" | |
"net/http" | |
"encoding/xml" | |
"database/sql" | |
pq "github.com/lib/pq" | |
mapset "github.com/deckarep/golang-set" | |
) | |
type DayRate struct { | |
Date *string `xml:"time,attr"` | |
Rates []Rate `xml:"Cube"` | |
} | |
type Rate struct { | |
Currency *string `xml:"currency,attr"` | |
Rate *float32 `xml:"rate,attr"` | |
} | |
func (dr *DayRate) NormalizeByUSD() { | |
var usd_coeff float32 = 1 | |
for _, rate := range dr.Rates { | |
// lookup USD | |
if *rate.Currency == "USD" { | |
usd_coeff = 1/ (*rate.Rate) | |
*rate.Rate = 1 | |
*rate.Currency = "EUR" | |
break | |
} | |
} | |
for _, rate := range dr.Rates { | |
// renormalize everything | |
*rate.Rate = usd_coeff * (*rate.Rate) | |
} | |
} | |
func inserter(comm chan *DayRate, done chan bool) { | |
// TODO: insert only new rates | |
currencies := mapset.NewSet() | |
db, err := sql.Open("postgres", "postgres://mtt:[email protected]/mtt?sslmode=disable") | |
if err != nil { log.Fatal(err) } | |
defer db.Close() | |
rows, err := db.Query("select code from currencies_currency") | |
if err != nil { log.Fatal(err) } | |
defer rows.Close() | |
for rows.Next() { | |
var code string | |
err = rows.Scan(&code) | |
if err != nil { log.Fatal(err) } | |
currencies.Add(code) | |
} | |
if err = rows.Err(); err != nil { log.Fatal(err) } | |
tx, err := db.Begin() | |
if err != nil { log.Fatal(err) } | |
stmt, err := tx.Prepare(pq.CopyIn("currencies_currencyrate", "currency_id", "date", "rate")) | |
if err != nil { log.Fatal(err) } | |
for { | |
dr, more := <- comm | |
if !more { break } | |
dr.NormalizeByUSD() | |
for _, rate := range dr.Rates { | |
if currencies.Contains(*rate.Currency) { | |
_, err = stmt.Exec(*rate.Currency, *dr.Date, *rate.Rate) | |
if err != nil { log.Fatal(err, *dr.Date, *rate.Currency, *rate.Rate) } | |
} | |
} | |
} | |
err = stmt.Close() | |
if err != nil { log.Fatal(err) } | |
err = tx.Commit() | |
if err != nil { log.Fatal(err) } | |
done <- true | |
} | |
func parser(comm chan *DayRate) { | |
defer close(comm) | |
response, err := http.Get("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.xml") | |
if err != nil { log.Fatal(err) } | |
defer response.Body.Close() | |
decoder := xml.NewDecoder(response.Body) | |
var level = 0 | |
for { | |
t, _ := decoder.Token() | |
if t == nil { break } | |
switch se := t.(type) { | |
case xml.StartElement: | |
if se.Name.Local == "Cube" { | |
if level == 1 { | |
var dr = new(DayRate) | |
decoder.DecodeElement(&dr, &se) | |
comm <- dr | |
} else { level += 1 } | |
} | |
case xml.EndElement: | |
if se.Name.Local == "Cube" { level -= 1 } | |
} | |
} | |
} | |
func main() { | |
comm := make(chan *DayRate, 10) | |
done := make(chan bool) | |
go inserter(comm, done) | |
go parser(comm) | |
<- done | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hi