[Scouting App] Add Driver Ranking

Move the driver ranking data collection from google forms to the scouting app.
The data collected is used to calculate a overall driver rank for the picklist.

Signed-off-by: Filip Kujawa <filip.j.kujawa@gmail.com>
Change-Id: Id459e8dec1fa79c1a9f49cc40ffa83014e51db16
diff --git a/scouting/db/db.go b/scouting/db/db.go
index 82f7fa8..55f2310 100644
--- a/scouting/db/db.go
+++ b/scouting/db/db.go
@@ -84,6 +84,20 @@
 	Rank, Dq           int32
 }
 
+type DriverRankingData struct {
+	// Each entry in the table is a single scout's ranking.
+	// Multiple scouts can submit a driver ranking for the same
+	// teams in the same match.
+	// The teams being ranked are stored in Rank1, Rank2, Rank3,
+	// Rank1 being the best driving and Rank3 being the worst driving.
+
+	ID          uint `gorm:"primaryKey"`
+	MatchNumber int32
+	Rank1       int32
+	Rank2       int32
+	Rank3       int32
+}
+
 // Opens a database at the specified port on localhost. We currently don't
 // support connecting to databases on other hosts.
 func NewDatabase(user string, password string, port int) (*Database, error) {
@@ -99,7 +113,7 @@
 		return nil, errors.New(fmt.Sprint("Failed to connect to postgres: ", err))
 	}
 
-	err = database.AutoMigrate(&Match{}, &Shift{}, &Stats{}, &NotesData{}, &Ranking{})
+	err = database.AutoMigrate(&Match{}, &Shift{}, &Stats{}, &NotesData{}, &Ranking{}, &DriverRankingData{})
 	if err != nil {
 		database.Delete()
 		return nil, errors.New(fmt.Sprint("Failed to create/migrate tables: ", err))
@@ -272,3 +286,19 @@
 	})
 	return result.Error
 }
+
+func (database *Database) AddDriverRanking(data DriverRankingData) error {
+	result := database.Create(&DriverRankingData{
+		MatchNumber: data.MatchNumber,
+		Rank1:       data.Rank1,
+		Rank2:       data.Rank2,
+		Rank3:       data.Rank3,
+	})
+	return result.Error
+}
+
+func (database *Database) QueryDriverRanking(MatchNumber int) ([]DriverRankingData, error) {
+	var data []DriverRankingData
+	result := database.Where("match_number = ?", MatchNumber).Find(&data)
+	return data, result.Error
+}
diff --git a/scouting/db/db_test.go b/scouting/db/db_test.go
index 1e11008..460b177 100644
--- a/scouting/db/db_test.go
+++ b/scouting/db/db_test.go
@@ -729,3 +729,33 @@
 		t.Errorf("Got %#v,\nbut expected %#v.", actual, expected)
 	}
 }
+
+func TestDriverRanking(t *testing.T) {
+	fixture := createDatabase(t)
+	defer fixture.TearDown()
+
+	expected := []DriverRankingData{
+		{ID: 1, MatchNumber: 12, Rank1: 1234, Rank2: 1235, Rank3: 1236},
+		{ID: 2, MatchNumber: 12, Rank1: 1236, Rank2: 1235, Rank3: 1234},
+	}
+
+	err := fixture.db.AddDriverRanking(
+		DriverRankingData{MatchNumber: 12, Rank1: 1234, Rank2: 1235, Rank3: 1236},
+	)
+	check(t, err, "Failed to add Driver Ranking")
+	err = fixture.db.AddDriverRanking(
+		DriverRankingData{MatchNumber: 12, Rank1: 1236, Rank2: 1235, Rank3: 1234},
+	)
+	check(t, err, "Failed to add Driver Ranking")
+	err = fixture.db.AddDriverRanking(
+		DriverRankingData{MatchNumber: 13, Rank1: 1235, Rank2: 1234, Rank3: 1236},
+	)
+	check(t, err, "Failed to add Driver Ranking")
+
+	actual, err := fixture.db.QueryDriverRanking(12)
+	check(t, err, "Failed to get Driver Ranking")
+
+	if !reflect.DeepEqual(expected, actual) {
+		t.Errorf("Got %#v,\nbut expected %#v.", actual, expected)
+	}
+}