Create scraping library to get match data

To use it, you need to make a JSON config file which gets stored
at the workspace root or you pass the path into the function(s)

Change-Id: I9d074c7ad84c45b418eb5be8b316a84b022db835
Signed-off-by: Het Satasiya <satasiyahet@gmail.com>
diff --git a/scouting/scraping/BUILD b/scouting/scraping/BUILD
new file mode 100644
index 0000000..58db2b1
--- /dev/null
+++ b/scouting/scraping/BUILD
@@ -0,0 +1,12 @@
+load("@io_bazel_rules_go//go:def.bzl", "go_library")
+
+go_library(
+    name = "scraping",
+    srcs = [
+        "scrape.go",
+        "types.go",
+    ],
+    importpath = "github.com/frc971/971-Robot-Code/scouting/scraping",
+    target_compatible_with = ["@platforms//cpu:x86_64"],
+    visibility = ["//visibility:public"],
+)
diff --git a/scouting/scraping/scrape.go b/scouting/scraping/scrape.go
new file mode 100644
index 0000000..fa20f7b
--- /dev/null
+++ b/scouting/scraping/scrape.go
@@ -0,0 +1,86 @@
+package scraping
+
+// A library to grab match data from The Blue Alliance.
+import (
+	"encoding/json"
+	"errors"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"os"
+)
+
+// Stores the TBA API key to access the API.
+type params struct {
+	ApiKey string `json:"api_key"`
+}
+
+// Takes in year and FIRST event code and returns all matches in that event according to TBA.
+// Also takes in a file path to the JSON config file that contains your TBA API key.
+// It defaults to <workspace root>/config.json
+// the config is expected to have the following contents:
+//{
+//    api_key:"myTBAapiKey"
+//}
+func AllMatches(year, eventCode, filePath string) ([]Match, error) {
+	if filePath == "" {
+		filePath = os.Getenv("BUILD_WORKSPACE_DIRECTORY") + "/scouting_config.json"
+	}
+	// Takes the filepath and grabs the api key from the json.
+	content, err := ioutil.ReadFile(filePath)
+	if err != nil {
+		log.Fatal(err)
+	}
+	// Parses the JSON parameters into a struct.
+	var passed_params params
+	error := json.Unmarshal([]byte(content), &passed_params)
+	if error != nil {
+		log.Fatalf("You forgot to add the api_key parameter in the json file")
+		log.Fatalf("%s", err)
+	}
+
+	// Create the TBA event key for the year and event code.
+	eventKey := year + eventCode
+
+	// Create the client for HTTP requests.
+	client := &http.Client{}
+
+	// Create a get request for the match info.
+	req, err := http.NewRequest("GET", "https://www.thebluealliance.com/api/v3/event/"+eventKey+"/matches", nil)
+
+	if err != nil {
+		return nil, errors.New("failed to build http request")
+	}
+
+	// Add the auth key header to the request.
+	req.Header.Add("X-TBA-Auth-Key", passed_params.ApiKey)
+
+	// Make the API request
+	resp, err := client.Do(req)
+
+	if err != nil {
+		return nil, err
+	}
+
+	if resp.Status != "200 OK" {
+		return nil, errors.New("Recieved a status of " + resp.Status + " expected : 200 OK")
+	}
+
+	// Wait until the response is done.
+	defer resp.Body.Close()
+
+	// Get all bytes from response body.
+	bodyBytes, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return nil, errors.New("failed to read response body with error :" + err.Error())
+	}
+
+	var matches []Match
+	// Unmarshal json into go usable format.
+	jsonError := json.Unmarshal([]byte(bodyBytes), &matches)
+	if jsonError != nil {
+		return nil, errors.New("failed to unmarshal json recieved from TBA")
+	}
+
+	return matches, nil
+}
diff --git a/scouting/scraping/types.go b/scouting/scraping/types.go
new file mode 100644
index 0000000..aa0d4be
--- /dev/null
+++ b/scouting/scraping/types.go
@@ -0,0 +1,82 @@
+package scraping
+
+// Match holds the TBA data for a given match
+type Match struct {
+	Key             string
+	CompLevel       string          `json:"comp_level"`
+	SetNumber       int             `json:"set_number"`
+	MatchNumber     int             `json:"match_number"`
+	Alliances       Alliances       `json:"alliances"`
+	WinningAlliance string          `json:"winning_alliance"`
+	EventKey        string          `json:"event_key"`
+	Time            int             `json:"time"`
+	PredictedTime   int             `json:"predicted_time"`
+	ActualTime      int             `json:"actual_time"`
+	PostResultTime  int             `json:"post_result_time"`
+	ScoreBreakdowns ScoreBreakdowns `json:"score_breakdowns"`
+}
+
+// Holds score breakdowns for each alliance
+type ScoreBreakdowns struct {
+	Blue ScoreBreakdownAlliance `json:"blue"`
+	Red  ScoreBreakdownAlliance `json:"red"`
+}
+
+// Stores the actual data for the breakdown
+type ScoreBreakdownAlliance struct {
+	TaxiRobot1    string `json:"taxiRobot1"`
+	EndgameRobot1 string `json:"endgameRobot1"`
+	TaxiRobot2    string `json:"taxiRobot2"`
+	EndgameRobot2 string `json:"endgameRobot2"`
+	TaxiRobot3    string `json:"taxiRobot3"`
+	EndgameRobot3 string `json:"endgameRobot3"`
+
+	AutoCargoLowerNear      int  `json:"autoCargoLowerNear"`
+	AutoCargoLowerFar       int  `json:"autoCargoLowerFar"`
+	AutoCargoLowerBlue      int  `json:"autoCargoLowerBlue"`
+	AutoCargoLowerRed       int  `json:"autoCargoLowerRed"`
+	AutoCargoUpperNear      int  `json:"autoCargoUpperNear"`
+	AutoCargoUpperFar       int  `json:"autoCargoUpperFar"`
+	AutoCargoUpperBlue      int  `json:"autoCargoUpperBlue"`
+	AutoCargoUpperRed       int  `json:"autoCargoUpperRed"`
+	AutoCargoTotal          int  `json:"autoCargoTotal"`
+	TeleOpCargoLowerNear    int  `json:"teleopCargoLowerNear"`
+	TeleOpCargoLowerFar     int  `json:"teleopCargoLowerFar"`
+	TeleOpCargoLowerBlue    int  `json:"teleopCargoLowerBlue"`
+	TeleOpCargoLowerRed     int  `json:"teleopCargoLowerRed"`
+	TeleOpCargoUpperNear    int  `json:"teleopCargoUpperNear"`
+	TeleOpCargoUpperFar     int  `json:"teleopCargoUpperFar"`
+	TeleOpCargoUpperBlue    int  `json:"teleopCargoUpperBlue"`
+	TeleOpCargoUpperRed     int  `json:"teleopCargoUpperRed"`
+	TeleopCargoTotal        int  `json:"teleopCargoTotal"`
+	MatchCargoTotal         int  `json:"matchCargoTotal"`
+	AutoTaxiPoints          int  `json:"autoTaxiPoints"`
+	AutoCargoPoints         int  `json:"autoCargoPoints"`
+	AutoPoints              int  `json:"autoPoints"`
+	QuintetAchieved         bool `json:"quintetAchieved"`
+	TeleOpCargoPoints       int  `json:"teleopCargoPoints"`
+	EndgamePoints           int  `json:"endgamePoints"`
+	TeleOpPoints            int  `json:"teleopPoints"`
+	CargoBonusRankingPoint  bool `json:"cargoBonusRankingPoint"`
+	HangerBonusRankingPoint bool `json:"hangarBonusRankingPoint"`
+	FoulCount               bool `json:"foulCount"`
+	TechFoulCount           int  `json:"techFoulCount"`
+	AdjustPoints            int  `json:"adjustPoints"`
+	FoulPoints              int  `json:"foulPoints"`
+	RankingPoints           int  `json:"rp"`
+	TotalPoints             int  `json:"totalPoints"`
+}
+
+// Alliances holds the two alliances for a match
+type Alliances struct {
+	Red  Alliance `json:"red"`
+	Blue Alliance `json:"blue"`
+}
+
+// Alliance holds the info for the alliance
+type Alliance struct {
+	Score             int      `json:"score"`
+	TeamKeys          []string `json:"team_keys"`
+	SurrogateTeamKeys []string `json:"surrogate_team_keys"`
+	DqTeamKeys        []string `json:"dq_team_keys"`
+}