Periodically refresh the match list for scouting

I've had a few instances where students thought that we didn't support
eliminations matches because they don't show up when first importing
the match list. The eliminations matches are only importable after the
alliance selections.

To work around this, the webserver now periodically imports the latest
match list. This means we don't need anyone to manually use the
"Import Match List" tab on the app anymore. I deleted that tab as
part of this patch.

The new `scouting/webserver/match_list/match_list.go` file is largely
just the code that I deleted from
`scouting/webserver/requests/requests.go`. I.e. it's really just
moving code around. The main difference now is that instead of
`requests.go` handling match list imports,
`scouting/webserver/main.go` now starts a background task to scrape
the match list every 10 minutes or so.

Signed-off-by: Philipp Schrader <philipp.schrader@gmail.com>
Change-Id: Ic37df45261f03a323069c1b38c4fd9682a9c4a3e
diff --git a/scouting/webserver/requests/requests_test.go b/scouting/webserver/requests/requests_test.go
index 27a45e6..ee22022 100644
--- a/scouting/webserver/requests/requests_test.go
+++ b/scouting/webserver/requests/requests_test.go
@@ -8,11 +8,8 @@
 	"testing"
 
 	"github.com/frc971/971-Robot-Code/scouting/db"
-	"github.com/frc971/971-Robot-Code/scouting/scraping"
 	"github.com/frc971/971-Robot-Code/scouting/webserver/requests/debug"
 	"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/error_response"
-	"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/refresh_match_list"
-	"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/refresh_match_list_response"
 	"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_driver_rankings"
 	"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_driver_rankings_response"
 	"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches"
@@ -37,7 +34,7 @@
 func Test404(t *testing.T) {
 	db := MockDatabase{}
 	scoutingServer := server.NewScoutingServer()
-	HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
+	HandleRequests(&db, scoutingServer)
 	scoutingServer.Start(8080)
 	defer scoutingServer.Stop()
 
@@ -54,7 +51,7 @@
 func TestSubmitDataScoutingError(t *testing.T) {
 	db := MockDatabase{}
 	scoutingServer := server.NewScoutingServer()
-	HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
+	HandleRequests(&db, scoutingServer)
 	scoutingServer.Start(8080)
 	defer scoutingServer.Stop()
 
@@ -82,7 +79,7 @@
 func TestSubmitDataScouting(t *testing.T) {
 	db := MockDatabase{}
 	scoutingServer := server.NewScoutingServer()
-	HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
+	HandleRequests(&db, scoutingServer)
 	scoutingServer.Start(8080)
 	defer scoutingServer.Stop()
 
@@ -201,7 +198,7 @@
 		},
 	}
 	scoutingServer := server.NewScoutingServer()
-	HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
+	HandleRequests(&db, scoutingServer)
 	scoutingServer.Start(8080)
 	defer scoutingServer.Stop()
 
@@ -267,7 +264,7 @@
 		},
 	}
 	scoutingServer := server.NewScoutingServer()
-	HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
+	HandleRequests(&db, scoutingServer)
 	scoutingServer.Start(8080)
 	defer scoutingServer.Stop()
 
@@ -322,7 +319,7 @@
 func TestSubmitNotes(t *testing.T) {
 	database := MockDatabase{}
 	scoutingServer := server.NewScoutingServer()
-	HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
+	HandleRequests(&database, scoutingServer)
 	scoutingServer.Start(8080)
 	defer scoutingServer.Stop()
 
@@ -375,7 +372,7 @@
 		}},
 	}
 	scoutingServer := server.NewScoutingServer()
-	HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
+	HandleRequests(&database, scoutingServer)
 	scoutingServer.Start(8080)
 	defer scoutingServer.Stop()
 
@@ -417,7 +414,7 @@
 		},
 	}
 	scoutingServer := server.NewScoutingServer()
-	HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
+	HandleRequests(&db, scoutingServer)
 	scoutingServer.Start(8080)
 	defer scoutingServer.Stop()
 
@@ -464,7 +461,7 @@
 func TestSubmitShiftSchedule(t *testing.T) {
 	database := MockDatabase{}
 	scoutingServer := server.NewScoutingServer()
-	HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
+	HandleRequests(&database, scoutingServer)
 	scoutingServer.Start(8080)
 	defer scoutingServer.Stop()
 
@@ -500,98 +497,10 @@
 	}
 }
 
-// Validates that we can download the schedule from The Blue Alliance.
-func TestRefreshMatchList(t *testing.T) {
-	scrapeMockSchedule := func(int32, string) ([]scraping.Match, error) {
-		return []scraping.Match{
-			{
-				CompLevel:   "qual",
-				MatchNumber: 1,
-				SetNumber:   2,
-				Alliances: scraping.Alliances{
-					Red: scraping.Alliance{
-						TeamKeys: []string{
-							"100",
-							"200",
-							"300",
-						},
-					},
-					Blue: scraping.Alliance{
-						TeamKeys: []string{
-							"101",
-							"201",
-							"301",
-						},
-					},
-				},
-				WinningAlliance: "",
-				EventKey:        "",
-				Time:            0,
-				PredictedTime:   0,
-				ActualTime:      0,
-				PostResultTime:  0,
-				ScoreBreakdowns: scraping.ScoreBreakdowns{},
-			},
-		}, nil
-	}
-
-	database := MockDatabase{}
-	scoutingServer := server.NewScoutingServer()
-	HandleRequests(&database, scrapeMockSchedule, scoutingServer)
-	scoutingServer.Start(8080)
-	defer scoutingServer.Stop()
-
-	builder := flatbuffers.NewBuilder(1024)
-	builder.Finish((&refresh_match_list.RefreshMatchListT{}).Pack(builder))
-
-	response, err := debug.RefreshMatchList("http://localhost:8080", builder.FinishedBytes())
-	if err != nil {
-		t.Fatal("Failed to request all matches: ", err)
-	}
-
-	// Validate the response.
-	expected := refresh_match_list_response.RefreshMatchListResponseT{}
-	if !reflect.DeepEqual(expected, *response) {
-		t.Fatal("Expected ", expected, ", but got ", *response)
-	}
-
-	// Make sure that the data made it into the database.
-	expectedMatches := []db.TeamMatch{
-		{
-			MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
-			Alliance: "R", AlliancePosition: 1, TeamNumber: 100,
-		},
-		{
-			MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
-			Alliance: "R", AlliancePosition: 2, TeamNumber: 200,
-		},
-		{
-			MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
-			Alliance: "R", AlliancePosition: 3, TeamNumber: 300,
-		},
-		{
-			MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
-			Alliance: "B", AlliancePosition: 1, TeamNumber: 101,
-		},
-		{
-			MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
-			Alliance: "B", AlliancePosition: 2, TeamNumber: 201,
-		},
-		{
-			MatchNumber: 1, SetNumber: 2, CompLevel: "qual",
-			Alliance: "B", AlliancePosition: 3, TeamNumber: 301,
-		},
-	}
-
-	if !reflect.DeepEqual(expectedMatches, database.matches) {
-		t.Fatal("Expected ", expectedMatches, ", but got ", database.matches)
-	}
-}
-
 func TestSubmitDriverRanking(t *testing.T) {
 	database := MockDatabase{}
 	scoutingServer := server.NewScoutingServer()
-	HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
+	HandleRequests(&database, scoutingServer)
 	scoutingServer.Start(8080)
 	defer scoutingServer.Stop()
 
@@ -636,7 +545,7 @@
 		},
 	}
 	scoutingServer := server.NewScoutingServer()
-	HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
+	HandleRequests(&db, scoutingServer)
 	scoutingServer.Start(8080)
 	defer scoutingServer.Stop()
 
@@ -701,7 +610,7 @@
 		},
 	}
 	scoutingServer := server.NewScoutingServer()
-	HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
+	HandleRequests(&db, scoutingServer)
 	scoutingServer.Start(8080)
 	defer scoutingServer.Stop()
 
@@ -820,8 +729,3 @@
 func (database *MockDatabase) ReturnAllDriverRankings() ([]db.DriverRankingData, error) {
 	return database.driver_ranking, nil
 }
-
-// Returns an empty match list from the fake The Blue Alliance scraping.
-func scrapeEmtpyMatchList(int32, string) ([]scraping.Match, error) {
-	return nil, nil
-}