Adding results and building results from it

This commit is contained in:
christalib 2020-07-26 01:41:30 +02:00
parent 56ad1acf3c
commit 40f9546b1a
10 changed files with 473 additions and 109 deletions

View file

@ -13,29 +13,6 @@ import (
"github.com/dgraph-io/dgo/v2/protos/api" "github.com/dgraph-io/dgo/v2/protos/api"
) )
// Driver represents a structure of driver entry in the Eargast API.
type Driver struct {
FirstName string `json:"givenName"`
LastName string `json:"familyName"`
DateOrBirth Date `json:"dateOfBirth"`
Nationality string `json:"nationality"`
}
// Drivers represents an array of driver in the Eargast API.
type Drivers struct {
Drivers []Driver `json:"Drivers"`
}
// DriverTable reprensts a table of drivers in the Eargast API.
type DriverTable struct {
DriverTable Drivers `json:"DriverTable"`
}
// MRDriverData is the wrapper for the datta in the Eargast API.
type MRDriverData struct {
MRData DriverTable `json:"MRData"`
}
// GetDriversFromErgast gets the driver data from the API. // GetDriversFromErgast gets the driver data from the API.
func GetDriversFromErgast(year string, client *dgo.Dgraph) { func GetDriversFromErgast(year string, client *dgo.Dgraph) {
resp, err := http.Get("http://ergast.com/api/f1/" + year + "/drivers.json") resp, err := http.Get("http://ergast.com/api/f1/" + year + "/drivers.json")
@ -66,7 +43,7 @@ func GetDriversFromErgast(year string, client *dgo.Dgraph) {
FirstName: driver.FirstName, FirstName: driver.FirstName,
LastName: driver.LastName, LastName: driver.LastName,
Nationality: driver.Nationality, Nationality: driver.Nationality,
DoB: (driver.DateOrBirth).Format(time.RFC3339), DoB: (driver.DateOfBirth).Format(time.RFC3339),
Type: "driver", Type: "driver",
} }
pb, err := json.Marshal(model) pb, err := json.Marshal(model)

View file

@ -15,52 +15,6 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
// Location represents the details of a circuit.
type Location struct {
Country string `json:"country"`
Latitude string `json:"lat"`
Locatlity string `json:"locality"`
Longitude string `json:"long"`
}
// Circuit represents the details of a circuit.
type Circuit struct {
CircuitID string `json:"circuitID"`
URL string `json:"url"`
Name string `json:"circuitName"`
Location Location `json:"Location"`
}
// Race represents the details of a race.
type Race struct {
Season string `json:"season"`
Round string `json:"round"`
RaceName string `json:"raceName"`
Circuit Circuit `json:"Circuit"`
Date Date `json:"date"`
Time string `json:"time"`
URL string `json:"url"`
}
// Races is the list of races.
type Races struct {
Races []Race `json:"Races"`
Season string `json:"season"`
}
// RaceTable is the list of races.
type RaceTable struct {
RaceTable Races `json:"RaceTable"`
}
// MRData is the general wrapper from Eargast API.
type MRData struct {
MRData RaceTable `json:"MRData"`
}
// Date is the date struct.
type Date struct{ time.Time }
// UnmarshalJSON is something. // UnmarshalJSON is something.
func (d *Date) UnmarshalJSON(data []byte) error { func (d *Date) UnmarshalJSON(data []byte) error {
t, err := time.Parse("2006-01-02", strings.Trim(string(data), "\"")) t, err := time.Parse("2006-01-02", strings.Trim(string(data), "\""))

View file

@ -1,34 +1,25 @@
package crawlers package crawlers
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"github.com/sirupsen/logrus"
)
// GetResultsFromErgast retrieves the results of the races from Ergast API. // GetResultsFromErgast retrieves the results of the races from Ergast API.
func GetResultsFromErgast(year string) { // func GetResultsFromErgast(year string) {
resp, err := http.Get("http://ergast.com/api/f1/results" + year + ".json") // resp, err := http.Get("http://ergast.com/api/f1/results" + year + ".json")
if err != nil { // if err != nil {
panic(err.Error()) // panic(err.Error())
} // }
body, err := ioutil.ReadAll(resp.Body) // body, err := ioutil.ReadAll(resp.Body)
if err != nil { // if err != nil {
panic(err.Error()) // panic(err.Error())
} // }
defer resp.Body.Close() // defer resp.Body.Close()
var jsonData MRData // var jsonData MRData
err = json.Unmarshal(body, &jsonData) // err = json.Unmarshal(body, &jsonData)
if err != nil { // if err != nil {
logrus.Error(err) // logrus.Error(err)
} // }
fmt.Println(jsonData) // fmt.Println(jsonData)
} // }
/** /**
MRDATA { MRDATA {

107
crawlers/results.go Normal file
View file

@ -0,0 +1,107 @@
package crawlers
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"github.com/dgraph-io/dgo/v2"
"github.com/dgraph-io/dgo/v2/protos/api"
"github.com/opentracing/opentracing-go/log"
)
// GetResultsFromErgast gets the results from the API based on a year and
// driver.
func GetResultsFromErgast(year string, driver string, client *dgo.Dgraph) {
// resp, err := http.Get("http://ergast.com/api/f1/" + year + "/" + driver + ".json")
resp, err := http.Get("http://ergast.com/api/f1/2019/drivers/vettel/results.json")
if err != nil {
log.Error(err)
}
if resp.StatusCode != 200 {
log.Message("Error not a 200 response")
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err.Error())
}
defer resp.Body.Close()
var jsonData MRData
err = json.Unmarshal(body, &jsonData)
if err != nil {
log.Error(err)
}
races := jsonData.MRData.RaceTable.Races
for _, race := range races {
ctx := context.Background()
mu := &api.Mutation{
CommitNow: true,
}
var results []Result
for _, result := range race.Results {
res := Result{
Number: result.Number,
Position: result.Position,
Points: result.Points,
Driver: Driver{
FirstName: result.Driver.FirstName,
LastName: result.Driver.LastName,
DateOfBirth: result.Driver.DateOfBirth,
Nationality: result.Driver.Nationality,
},
// Constructor: result.Constructor{},
Grid: result.Grid,
Laps: result.Laps,
Status: result.Status,
Time: result.Time,
// FastestLap: result.FastestLap{},
// AverageSpeed: result.AverageSpeed{},
}
results = append(results, res)
}
model := Race{
Season: race.Season,
Round: race.Round,
RaceName: race.RaceName,
Circuit: Circuit{
CircuitID: race.Circuit.CircuitID,
URL: race.Circuit.URL,
Name: race.Circuit.Name,
Location: Location{
Country: race.Circuit.Location.Country,
Latitude: race.Circuit.Location.Latitude,
Locality: race.Circuit.Location.Locality,
Longitude: race.Circuit.Location.Longitude,
},
},
Results: results,
Date: race.Date,
Time: race.Time,
}
pb, err := json.Marshal(model)
if err != nil {
log.Error(err)
}
mu.SetJson = pb
data, err := client.NewTxn().Mutate(ctx, mu)
if err != nil {
log.Error(err)
}
fmt.Print(data)
}
}

180
crawlers/results.json Normal file
View file

@ -0,0 +1,180 @@
{
"MRData": {
"xmlns": "http://ergast.com/mrd/1.4",
"series": "f1",
"url": "http://ergast.com/api/f1/2020/drivers/vettel/results.json",
"limit": "30",
"offset": "0",
"total": "3",
"RaceTable": {
"season": "2020",
"driverId": "vettel",
"Races": [
{
"season": "2020",
"round": "1",
"url": "https://en.wikipedia.org/wiki/2020_Austrian_Grand_Prix",
"raceName": "Austrian Grand Prix",
"Circuit": {
"circuitId": "red_bull_ring",
"url": "http://en.wikipedia.org/wiki/Red_Bull_Ring",
"circuitName": "Red Bull Ring",
"Location": {
"lat": "47.2197",
"long": "14.7647",
"locality": "Spielburg",
"country": "Austria"
}
},
"date": "2020-07-05",
"time": "13:10:00Z",
"Results": [
{
"number": "5",
"position": "10",
"positionText": "10",
"points": "1",
"Driver": {
"driverId": "vettel",
"permanentNumber": "5",
"code": "VET",
"url": "http://en.wikipedia.org/wiki/Sebastian_Vettel",
"givenName": "Sebastian",
"familyName": "Vettel",
"dateOfBirth": "1987-07-03",
"nationality": "German"
},
"Constructor": {
"constructorId": "ferrari",
"url": "http://en.wikipedia.org/wiki/Scuderia_Ferrari",
"name": "Ferrari",
"nationality": "Italian"
},
"grid": "11",
"laps": "71",
"status": "Finished",
"Time": {
"millis": "5480284",
"time": "+24.545"
},
"FastestLap": {
"rank": "8",
"lap": "71",
"Time": {
"time": "1:08.623"
},
"AverageSpeed": {
"units": "kph",
"speed": "226.524"
}
}
}
]
},
{
"season": "2020",
"round": "2",
"url": "https://en.wikipedia.org/wiki/2020_Styrian_Grand_Prix",
"raceName": "Styrian Grand Prix",
"Circuit": {
"circuitId": "red_bull_ring",
"url": "http://en.wikipedia.org/wiki/Red_Bull_Ring",
"circuitName": "Red Bull Ring",
"Location": {
"lat": "47.2197",
"long": "14.7647",
"locality": "Spielburg",
"country": "Austria"
}
},
"date": "2020-07-12",
"time": "13:10:00Z",
"Results": [
{
"number": "5",
"position": "20",
"positionText": "R",
"points": "0",
"Driver": {
"driverId": "vettel",
"permanentNumber": "5",
"code": "VET",
"url": "http://en.wikipedia.org/wiki/Sebastian_Vettel",
"givenName": "Sebastian",
"familyName": "Vettel",
"dateOfBirth": "1987-07-03",
"nationality": "German"
},
"Constructor": {
"constructorId": "ferrari",
"url": "http://en.wikipedia.org/wiki/Scuderia_Ferrari",
"name": "Ferrari",
"nationality": "Italian"
},
"grid": "10",
"laps": "1",
"status": "Collision damage"
}
]
},
{
"season": "2020",
"round": "3",
"url": "https://en.wikipedia.org/wiki/2020_Hungarian_Grand_Prix",
"raceName": "Hungarian Grand Prix",
"Circuit": {
"circuitId": "hungaroring",
"url": "http://en.wikipedia.org/wiki/Hungaroring",
"circuitName": "Hungaroring",
"Location": {
"lat": "47.5789",
"long": "19.2486",
"locality": "Budapest",
"country": "Hungary"
}
},
"date": "2020-07-19",
"time": "13:10:00Z",
"Results": [
{
"number": "5",
"position": "6",
"positionText": "6",
"points": "8",
"Driver": {
"driverId": "vettel",
"permanentNumber": "5",
"code": "VET",
"url": "http://en.wikipedia.org/wiki/Sebastian_Vettel",
"givenName": "Sebastian",
"familyName": "Vettel",
"dateOfBirth": "1987-07-03",
"nationality": "German"
},
"Constructor": {
"constructorId": "ferrari",
"url": "http://en.wikipedia.org/wiki/Scuderia_Ferrari",
"name": "Ferrari",
"nationality": "Italian"
},
"grid": "5",
"laps": "69",
"status": "+1 Lap",
"FastestLap": {
"rank": "14",
"lap": "49",
"Time": {
"time": "1:20.363"
},
"AverageSpeed": {
"units": "kph",
"speed": "196.254"
}
}
}
]
}
]
}
}
}

114
crawlers/types.go Normal file
View file

@ -0,0 +1,114 @@
package crawlers
import "time"
// Driver represents a structure of driver entry in the Eargast API.
type Driver struct {
FirstName string `json:"givenName,omitemtpy"`
LastName string `json:"familyName,omitemtpy"`
DateOfBirth Date `json:"dateOfBirth,omitemtpy"`
Nationality string `json:"nationality,omitemtpy"`
}
// Drivers represents an array of driver in the Eargast API.
type Drivers struct {
Drivers []Driver `json:"Drivers,omitemtpy"`
}
// DriverTable reprensts a table of drivers in the Eargast API.
type DriverTable struct {
DriverTable Drivers `json:"DriverTable,omitemtpy"`
}
// MRData is the general wrapper from Eargast API.
type MRData struct {
MRData RaceTable `json:"MRData,omitempty"`
}
// MRDriverData is the wrapper for the datta in the Eargast API.
type MRDriverData struct {
MRData DriverTable `json:"MRData,omitemtpy"`
}
// Location represents the details of a circuit.
type Location struct {
Country string `json:"country,omitempty"`
Latitude string `json:"lat,omitempty"`
Locality string `json:"locality,omitempty"`
Longitude string `json:"long,omitempty"`
}
// Circuit represents the details of a circuit.
type Circuit struct {
CircuitID string `json:"circuitID,omitempty"`
URL string `json:"url,omitempty"`
Name string `json:"circuitName,omitempty"`
Location Location `json:"Location,omitempty"`
}
// Race represents the details of a race.
type Race struct {
Season string `json:"season,omitempty"`
Round string `json:"round,omitempty"`
RaceName string `json:"raceName,omitempty"`
Circuit Circuit `json:"Circuit,omitempty"`
Date Date `json:"date,omitempty"`
Time string `json:"time,omitempty"`
URL string `json:"url,omitempty"`
Results []Result `json:"Results,omitempty"`
}
// Races is the list of races.
type Races struct {
Races []Race `json:"Races,omitempty"`
// Season string `json:"season,omitempty"`
}
// RaceTable is the list of races.
type RaceTable struct {
RaceTable Races `json:"RaceTable,omitempty"`
}
// Date is the date struct.
type Date struct{ time.Time }
type Constructor struct {
ConstructorID string `json:"constructorID,omitempty"`
URL string `json:"url,omitempty"`
Name string `json:"name,omitempty"`
Nationality string `json:"nationality,omitempty"`
}
type FastestLap struct {
Rank string `json:"rank,omitempty"`
Lap string `json:"lap,omitempty"`
Time Time `json:"time,omitempty"`
}
type Time struct {
Millis string `json:"millis,omitempty"`
Time string `json:"time,omitempty"`
}
type AverageSpeed struct {
Units string `json:"units,omitempty"`
Speed string `json:"speed,omitempty"`
}
type Result struct {
Number string `json:"numbe,omitemptyr"`
Position string `json:"position,omitempty"`
Points string `json:"points,omitempty"`
Driver Driver `json:"driver,omitempty"`
Constructor Constructor `json:"Constructor,omitempty"`
Grid string `json:"grid,omitempty"`
Laps string `json:"laps,omitempty"`
Status string `json:"status,omitempty"`
Time Time `json:"time,omitempty"`
FastestLap FastestLap `json:"FastestLap,omitempty"`
AverageSpeed AverageSpeed `json:"AvergareSpeed,omitempty"`
}
type Results struct {
Results []Result `json:"Result,omitempty"`
}

1
go.mod
View file

@ -7,6 +7,7 @@ require (
github.com/dgraph-io/dgo/v2 v2.2.0 github.com/dgraph-io/dgo/v2 v2.2.0
github.com/go-sql-driver/mysql v1.4.1 github.com/go-sql-driver/mysql v1.4.1
github.com/jinzhu/gorm v1.9.11 github.com/jinzhu/gorm v1.9.11
github.com/opentracing/opentracing-go v1.2.0
github.com/sirupsen/logrus v1.2.0 github.com/sirupsen/logrus v1.2.0
github.com/urfave/cli v1.22.4 github.com/urfave/cli v1.22.4
github.com/urfave/cli/v2 v2.2.0 // indirect github.com/urfave/cli/v2 v2.2.0 // indirect

3
go.sum
View file

@ -81,6 +81,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -110,6 +112,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA= github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=

View file

@ -22,12 +22,38 @@ func ConnectToDgraph() (*dgo.Dgraph, error) {
func InitSchema(c *dgo.Dgraph) error { func InitSchema(c *dgo.Dgraph) error {
err := c.Alter(context.Background(), &api.Operation{ err := c.Alter(context.Background(), &api.Operation{
DropAll: true,
Schema: ` Schema: `
firstName: string . averageSpeed: uid .
lastName: string @index(term) . circuit: uid .
nationality: string @index(term) . constructor: uid .
constructorId: string .
date: string .
dob: string . dob: string .
driver: uid .
fastestLap: uid .
firstName: string .
grid: string .
lap: string .
laps: string .
lastName: string @index(term) .
location: string @index(term) .
millis: string .
name: string @index(term) .
nationality: string @index(term) .
number: string .
points: string .
position: string @index(term) .
raceName: string @index(term) .
rank: string .
round: string .
season: string @index(term) .
speed: string .
status: string .
time: string .
type: string @index(term) . type: string @index(term) .
units: string .
url: string .
type Driver { type Driver {
firstName: string firstName: string
@ -37,12 +63,24 @@ dob: string
type: string type: string
} }
season: string @index(term) . type Constructor {
round: string . constructorId: string
raceName: string @index(term) . url: string
circuit: uid . name: string
date: string . nationality: string
url: string . }
type Result {
number: string
position: string
points: string
driver: Driver
constructor: Constructor
grid: string
laps: string
status: string
time: Time
}
type Circuit { type Circuit {
name: string name: string
@ -61,8 +99,6 @@ url: string
type: string type: string
} }
name: string @index(term) .
location: string @index(term) .
`}) `})
if err != nil { if err != nil {

View file

@ -29,7 +29,8 @@ func main() {
app.Description = "Run with the docker-compose file and the app will data from Ergast and display it in Dgraph." app.Description = "Run with the docker-compose file and the app will data from Ergast and display it in Dgraph."
fmt.Println("Hello there! It is", year) fmt.Println("Hello there! It is", year)
crawlers.GetSeasonFromErgast(year, client) crawlers.GetResultsFromErgast(year, "alonso", client)
crawlers.GetDriversFromErgast(year, client) // crawlers.GetSeasonFromErgast(year, client)
// crawlers.GetDriversFromErgast(year, client)
// crawlers.GetResultsFromErgast(year) // crawlers.GetResultsFromErgast(year)
} }