Merge "Split 2022 vision math code into library"
diff --git a/BUILD b/BUILD
index 232ac67..0d79e19 100644
--- a/BUILD
+++ b/BUILD
@@ -15,12 +15,14 @@
# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/error_response //scouting/webserver/requests/messages:error_response_go_fbs
# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting //scouting/webserver/requests/messages:submit_data_scouting_go_fbs
# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting_response //scouting/webserver/requests/messages:submit_data_scouting_response_go_fbs
-# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting_response //scouting/webserver/requests/messages:query_data_scouting_response_go_fbs
+# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting_response //scouting/webserver/requests/messages:request_data_scouting_response_go_fbs
# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting //scouting/webserver/requests/messages:request_data_scouting_go_fbs
# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team_response //scouting/webserver/requests/messages:request_matches_for_team_response_go_fbs
# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team //scouting/webserver/requests/messages:request_matches_for_team_go_fbs
# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches_response //scouting/webserver/requests/messages:request_all_matches_response_go_fbs
# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches //scouting/webserver/requests/messages:request_all_matches_go_fbs
+# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/refresh_match_list //scouting/webserver/requests/messages:refresh_match_list_go_fbs
+# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/refresh_match_list_response //scouting/webserver/requests/messages:refresh_match_list_response_go_fbs
gazelle(
name = "gazelle",
diff --git a/WORKSPACE b/WORKSPACE
index acda914..398202c 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -752,7 +752,7 @@
# I'm sure there is a better path, but that works...
yarn_install(
name = "npm",
- frozen_lockfile = False,
+ frozen_lockfile = True,
package_json = "//:package.json",
symlink_node_modules = False,
yarn_lock = "//:yarn.lock",
diff --git a/frc971/analysis/BUILD b/frc971/analysis/BUILD
index 686529f..20f1a01 100644
--- a/frc971/analysis/BUILD
+++ b/frc971/analysis/BUILD
@@ -53,6 +53,9 @@
"//y2020/control_loops/superstructure:turret_plotter",
"//y2021_bot3/control_loops/superstructure:superstructure_plotter",
"//y2022/control_loops/superstructure:catapult_plotter",
+ "//y2022/control_loops/superstructure:climber_plotter",
+ "//y2022/control_loops/superstructure:intake_plotter",
+ "//y2022/control_loops/superstructure:turret_plotter",
"//y2022/localizer:localizer_plotter",
],
)
diff --git a/frc971/analysis/plot_index.ts b/frc971/analysis/plot_index.ts
index 332db34..bbaa0ce 100644
--- a/frc971/analysis/plot_index.ts
+++ b/frc971/analysis/plot_index.ts
@@ -28,22 +28,28 @@
import {plotDownEstimator} from 'org_frc971/frc971/control_loops/drivetrain/down_estimator_plotter';
import {plotRobotState} from
'org_frc971/frc971/control_loops/drivetrain/robot_state_plotter'
-import {plotFinisher} from
+import {plotFinisher as plot2020Finisher} from
'org_frc971/y2020/control_loops/superstructure/finisher_plotter'
-import {plotTurret} from
+import {plotTurret as plot2020Turret} from
'org_frc971/y2020/control_loops/superstructure/turret_plotter'
import {plotLocalizer as plot2020Localizer} from
'org_frc971/y2020/control_loops/drivetrain/localizer_plotter'
+import {plotAccelerator as plot2020Accelerator} from
+ 'org_frc971/y2020/control_loops/superstructure/accelerator_plotter'
+import {plotHood as plot2020Hood} from
+ 'org_frc971/y2020/control_loops/superstructure/hood_plotter'
+import {plotSuperstructure as plot2021Superstructure} from
+ 'org_frc971/y2021_bot3/control_loops/superstructure/superstructure_plotter';
+import {plotTurret as plot2022Turret} from
+ 'org_frc971/y2022/control_loops/superstructure/turret_plotter'
import {plotCatapult as plot2022Catapult} from
'org_frc971/y2022/control_loops/superstructure/catapult_plotter'
+import {plotIntakeFront as plot2022IntakeFront, plotIntakeBack as plot2022IntakeBack} from
+ 'org_frc971/y2022/control_loops/superstructure/intake_plotter'
+import {plotClimber as plot2022Climber} from
+ 'org_frc971/y2022/control_loops/superstructure/climber_plotter'
import {plotLocalizer as plot2022Localizer} from
'org_frc971/y2022/localizer/localizer_plotter'
-import {plotAccelerator} from
- 'org_frc971/y2020/control_loops/superstructure/accelerator_plotter'
-import {plotHood} from
- 'org_frc971/y2020/control_loops/superstructure/hood_plotter'
-import {plotSuperstructure} from
- 'org_frc971/y2021_bot3/control_loops/superstructure/superstructure_plotter';
import {plotDemo} from 'org_frc971/aos/network/www/demo_plot';
import {plotData} from 'org_frc971/frc971/analysis/plot_data_utils';
@@ -104,15 +110,19 @@
['Spline Debug', new PlotState(plotDiv, plotSpline)],
['Down Estimator', new PlotState(plotDiv, plotDownEstimator)],
['Robot State', new PlotState(plotDiv, plotRobotState)],
- ['Finisher', new PlotState(plotDiv, plotFinisher)],
- ['Accelerator', new PlotState(plotDiv, plotAccelerator)],
- ['Hood', new PlotState(plotDiv, plotHood)],
- ['Turret', new PlotState(plotDiv, plotTurret)],
- ['2022 Localizer', new PlotState(plotDiv, plot2022Localizer)],
+ ['2020 Finisher', new PlotState(plotDiv, plot2020Finisher)],
+ ['2020 Accelerator', new PlotState(plotDiv, plot2020Accelerator)],
+ ['2020 Hood', new PlotState(plotDiv, plot2020Hood)],
+ ['2020 Turret', new PlotState(plotDiv, plot2020Turret)],
['2020 Localizer', new PlotState(plotDiv, plot2020Localizer)],
+ ['2022 Localizer', new PlotState(plotDiv, plot2022Localizer)],
['2022 Catapult', new PlotState(plotDiv, plot2022Catapult)],
+ ['2022 Intake Front', new PlotState(plotDiv, plot2022IntakeFront)],
+ ['2022 Intake Back', new PlotState(plotDiv, plot2022IntakeBack)],
+ ['2022 Climber', new PlotState(plotDiv, plot2022Climber)],
+ ['2022 Turret', new PlotState(plotDiv, plot2022Turret)],
['C++ Plotter', new PlotState(plotDiv, plotData)],
- ['Y2021 3rd Robot Superstructure', new PlotState(plotDiv, plotSuperstructure)],
+ ['Y2021 3rd Robot Superstructure', new PlotState(plotDiv, plot2021Superstructure)],
]);
const invalidSelectValue = 'null';
diff --git a/frc971/control_loops/python/constants.py b/frc971/control_loops/python/constants.py
index b515626..0a3ad18 100644
--- a/frc971/control_loops/python/constants.py
+++ b/frc971/control_loops/python/constants.py
@@ -33,6 +33,7 @@
Robot2019 = RobotType(width=0.65, length=0.8)
Robot2020 = RobotType(width=0.8128, length=0.8636) # 32 in x 34 in
Robot2021 = Robot2020
+Robot2022 = Robot2021
FIELDS = {
"2019 Field":
@@ -116,14 +117,25 @@
length=4.572,
robot=Robot2021,
field_id="autonav_bounce"),
+ "2022 Field":
+ FieldType(
+ "2022 Field",
+ tags=[],
+ year=2022,
+ width=16.4592,
+ length=8.2296,
+ robot=Robot2022,
+ field_id="2022"),
}
-FIELD = FIELDS["2020 Field"]
+FIELD = FIELDS["2022 Field"]
def get_json_folder(field):
if field.year == 2020 or field.year == 2021:
return "y2020/actors/splines"
+ elif field.year == 2022:
+ return "y2022/actors/splines"
else:
return "frc971/control_loops/python/spline_jsons"
diff --git a/frc971/control_loops/python/field_images/2022.png b/frc971/control_loops/python/field_images/2022.png
new file mode 100644
index 0000000..68087bd
--- /dev/null
+++ b/frc971/control_loops/python/field_images/2022.png
Binary files differ
diff --git a/frc971/control_loops/python/path_edit.py b/frc971/control_loops/python/path_edit.py
index df460d3..35a670c 100755
--- a/frc971/control_loops/python/path_edit.py
+++ b/frc971/control_loops/python/path_edit.py
@@ -7,7 +7,6 @@
import gi
import numpy as np
gi.require_version('Gtk', '3.0')
-gi.require_version('Gdk', '3.0')
from gi.repository import Gdk, Gtk, GLib
import cairo
from libspline import Spline
@@ -57,7 +56,7 @@
self.held_x = 0
self.spline_edit = -1
- self.transform = cairo.Matrix()
+ self.zoom_transform = cairo.Matrix()
self.set_events(Gdk.EventMask.BUTTON_PRESS_MASK
| Gdk.EventMask.BUTTON_PRESS_MASK
@@ -73,16 +72,28 @@
self.field.field_id + ".png")
except cairo.Error:
self.field_png = None
+
self.queue_draw()
+ def invert(self, transform):
+ xx, yx, xy, yy, x0, y0 = transform
+ matrix = cairo.Matrix(xx, yx, xy, yy, x0, y0)
+ matrix.invert()
+ return matrix
+
# returns the transform from widget space to field space
@property
def input_transform(self):
- xx, yx, xy, yy, x0, y0 = self.transform
- matrix = cairo.Matrix(xx, yx, xy, yy, x0, y0)
# the transform for input needs to be the opposite of the transform for drawing
- matrix.invert()
- return matrix
+ return self.invert(self.field_transform.multiply(self.zoom_transform))
+
+ @property
+ def field_transform(self):
+ field_transform = cairo.Matrix()
+ field_transform.scale(1, -1) # flipped y-axis
+ field_transform.scale(1 / self.pxToM_scale(), 1 / self.pxToM_scale())
+ field_transform.translate(self.field.width / 2, -1 * self.field.length / 2)
+ return field_transform
# returns the scale from pixels in field space to meters in field space
def pxToM_scale(self):
@@ -97,19 +108,19 @@
return m / self.pxToM_scale()
def draw_robot_at_point(self, cr, i, p, spline):
- p1 = [self.mToPx(spline.Point(i)[0]), self.mToPx(spline.Point(i)[1])]
+ p1 = [spline.Point(i)[0], spline.Point(i)[1]]
p2 = [
- self.mToPx(spline.Point(i + p)[0]),
- self.mToPx(spline.Point(i + p)[1])
+ spline.Point(i + p)[0],
+ spline.Point(i + p)[1]
]
#Calculate Robot
distance = np.sqrt((p2[1] - p1[1])**2 + (p2[0] - p1[0])**2)
x_difference_o = p2[0] - p1[0]
y_difference_o = p2[1] - p1[1]
- x_difference = x_difference_o * self.mToPx(
+ x_difference = x_difference_o * (
self.field.robot.length / 2) / distance
- y_difference = y_difference_o * self.mToPx(
+ y_difference = y_difference_o * (
self.field.robot.length / 2) / distance
front_middle = []
@@ -123,9 +134,9 @@
slope = [-(1 / x_difference_o) / (1 / y_difference_o)]
angle = np.arctan(slope)
- x_difference = np.sin(angle[0]) * self.mToPx(
+ x_difference = np.sin(angle[0]) * (
self.field.robot.width / 2)
- y_difference = np.cos(angle[0]) * self.mToPx(
+ y_difference = np.cos(angle[0]) * (
self.field.robot.width / 2)
front_1 = []
@@ -144,9 +155,9 @@
back_2.append(back_middle[0] + x_difference)
back_2.append(back_middle[1] + y_difference)
- x_difference = x_difference_o * self.mToPx(
+ x_difference = x_difference_o * (
self.field.robot.length / 2 + ROBOT_SIDE_TO_BALL_CENTER) / distance
- y_difference = y_difference_o * self.mToPx(
+ y_difference = y_difference_o * (
self.field.robot.length / 2 + ROBOT_SIDE_TO_BALL_CENTER) / distance
#Calculate Ball
@@ -154,9 +165,9 @@
ball_center.append(p1[0] + x_difference)
ball_center.append(p1[1] + y_difference)
- x_difference = x_difference_o * self.mToPx(
+ x_difference = x_difference_o * (
self.field.robot.length / 2 + ROBOT_SIDE_TO_HATCH_PANEL) / distance
- y_difference = y_difference_o * self.mToPx(
+ y_difference = y_difference_o * (
self.field.robot.length / 2 + ROBOT_SIDE_TO_HATCH_PANEL) / distance
#Calculate Panel
@@ -164,8 +175,8 @@
panel_center.append(p1[0] + x_difference)
panel_center.append(p1[1] + y_difference)
- x_difference = np.sin(angle[0]) * self.mToPx(HATCH_PANEL_WIDTH / 2)
- y_difference = np.cos(angle[0]) * self.mToPx(HATCH_PANEL_WIDTH / 2)
+ x_difference = np.sin(angle[0]) * (HATCH_PANEL_WIDTH / 2)
+ y_difference = np.cos(angle[0]) * (HATCH_PANEL_WIDTH / 2)
panel_1 = []
panel_1.append(panel_center[0] + x_difference)
@@ -188,7 +199,7 @@
set_color(cr, palette["ORANGE"], 0.5)
cr.move_to(back_middle[0], back_middle[1])
cr.line_to(ball_center[0], ball_center[1])
- cr.arc(ball_center[0], ball_center[1], self.mToPx(BALL_RADIUS), 0,
+ cr.arc(ball_center[0], ball_center[1], BALL_RADIUS, 0,
2 * np.pi)
cr.stroke()
@@ -201,23 +212,24 @@
cr.set_source_rgba(0, 0, 0, 1)
def do_draw(self, cr): # main
- cr.set_matrix(self.transform.multiply(cr.get_matrix()))
+ cr.set_matrix(self.field_transform.multiply(self.zoom_transform).multiply(cr.get_matrix()))
cr.save()
set_color(cr, palette["BLACK"])
- cr.set_line_width(1.0)
- cr.rectangle(0, 0, self.mToPx(self.field.width),
- self.mToPx(self.field.length))
+ cr.set_line_width(self.pxToM(2))
+ cr.rectangle(-0.5 * self.field.width, -0.5 * self.field.length, self.field.width,
+ self.field.length)
cr.set_line_join(cairo.LINE_JOIN_ROUND)
cr.stroke()
if self.field_png:
cr.save()
+ cr.translate(-0.5 * self.field.width, 0.5 * self.field.length)
cr.scale(
- self.mToPx(self.field.width) / self.field_png.get_width(),
- self.mToPx(self.field.length) / self.field_png.get_height(),
+ self.field.width / self.field_png.get_width(),
+ -self.field.length / self.field_png.get_height(),
)
cr.set_source_surface(self.field_png)
cr.paint()
@@ -225,11 +237,11 @@
# update everything
- cr.set_line_width(2.0)
+ cr.set_line_width(self.pxToM(2))
if self.mode == Mode.kPlacing or self.mode == Mode.kViewing:
set_color(cr, palette["BLACK"])
for i, point in enumerate(self.points.getPoints()):
- draw_px_x(cr, self.mToPx(point[0]), self.mToPx(point[1]), 10)
+ draw_px_x(cr, point[0], point[1], self.pxToM(5))
set_color(cr, palette["WHITE"])
elif self.mode == Mode.kEditing:
set_color(cr, palette["BLACK"])
@@ -237,17 +249,17 @@
self.draw_splines(cr)
for i, points in enumerate(self.points.getSplines()):
points = [
- np.array([self.mToPx(x), self.mToPx(y)])
+ np.array([x, y])
for (x, y) in points
]
- draw_control_points(cr, points)
+ draw_control_points(cr, points, width=self.pxToM(10), radius=self.pxToM(4))
p0, p1, p2, p3, p4, p5 = points
first_tangent = p0 + 2.0 * (p1 - p0)
second_tangent = p5 + 2.0 * (p4 - p5)
cr.set_source_rgb(0, 0.5, 0)
cr.move_to(p0[0], p0[1])
- cr.set_line_width(1.0)
+ cr.set_line_width(self.pxToM(1.0))
cr.line_to(first_tangent[0], first_tangent[1])
cr.move_to(first_tangent[0], first_tangent[1])
cr.line_to(p2[0], p2[1])
@@ -259,27 +271,27 @@
cr.line_to(p3[0], p3[1])
cr.stroke()
- cr.set_line_width(2.0)
+ cr.set_line_width(self.pxToM(2))
set_color(cr, palette["WHITE"])
cr.paint_with_alpha(0.2)
- draw_px_cross(cr, self.mousex, self.mousey, 10)
+ draw_px_cross(cr, self.mousex, self.mousey, self.pxToM(8))
cr.restore()
def draw_splines(self, cr):
for i, spline in enumerate(self.points.getLibsplines()):
- for k in np.linspace(0.01, 1, 100):
+ for k in np.linspace(0.02, 1, 200):
cr.move_to(
- self.mToPx(spline.Point(k - 0.01)[0]),
- self.mToPx(spline.Point(k - 0.01)[1]))
+ spline.Point(k - 0.008)[0],
+ spline.Point(k - 0.008)[1])
cr.line_to(
- self.mToPx(spline.Point(k)[0]),
- self.mToPx(spline.Point(k)[1]))
+ spline.Point(k)[0],
+ spline.Point(k)[1])
cr.stroke()
if i == 0:
- self.draw_robot_at_point(cr, 0.00, 0.01, spline)
- self.draw_robot_at_point(cr, 1, 0.01, spline)
+ self.draw_robot_at_point(cr, 0, 0.008, spline)
+ self.draw_robot_at_point(cr, 1, 0.008, spline)
def export_json(self, file_name):
self.path_to_export = os.path.join(
@@ -394,8 +406,8 @@
if self.mode == Mode.kEditing:
if self.index_of_edit > -1 and self.held_x != self.mousex:
self.points.setSplines(self.spline_edit, self.index_of_edit,
- self.pxToM(self.mousex),
- self.pxToM(self.mousey))
+ self.mousex,
+ self.mousey)
self.points.splineExtrapolate(self.spline_edit)
@@ -411,7 +423,7 @@
if self.mode == Mode.kPlacing:
if self.points.add_point(
- self.pxToM(self.mousex), self.pxToM(self.mousey)):
+ self.mousex, self.mousey):
self.mode = Mode.kEditing
self.graph.schedule_recalculate(self.points)
elif self.mode == Mode.kEditing:
@@ -421,7 +433,7 @@
# Get clicked point
# Find nearest
# Move nearest to clicked
- cur_p = [self.pxToM(self.mousex), self.pxToM(self.mousey)]
+ cur_p = [self.mousex, self.mousey]
# Get the distance between each for x and y
# Save the index of the point closest
nearest = 1 # Max distance away a the selected point can be in meters
@@ -448,23 +460,24 @@
event.x, event.y)
dif_x = self.mousex - old_x
dif_y = self.mousey - old_y
- difs = np.array([self.pxToM(dif_x), self.pxToM(dif_y)])
+ difs = np.array([dif_x, dif_y])
if self.mode == Mode.kEditing and self.spline_edit != -1:
self.points.updates_for_mouse_move(self.index_of_edit,
self.spline_edit,
- self.pxToM(self.mousex),
- self.pxToM(self.mousey), difs)
+ self.mousex,
+ self.mousey, difs)
self.points.update_lib_spline()
self.graph.schedule_recalculate(self.points)
self.queue_draw()
def do_scroll_event(self, event):
+
self.mousex, self.mousey = self.input_transform.transform_point(
event.x, event.y)
- step_size = 20 # px
+ step_size = self.pxToM(20) # px
if event.direction == Gdk.ScrollDirection.UP:
# zoom out
@@ -475,32 +488,27 @@
else:
return
- apparent_width, apparent_height = self.transform.transform_distance(
- self.mToPx(FIELD.width), self.mToPx(FIELD.length))
- scale = (apparent_width + scale_by) / apparent_width
-
- # scale from point in field coordinates
- point = self.mousex, self.mousey
+ scale = (self.field.width + scale_by) / self.field.width
# This restricts the amount it can be scaled.
- if self.transform.xx <= 0.75:
+ if self.zoom_transform.xx <= 0.5:
scale = max(scale, 1)
- elif self.transform.xx >= 16:
+ elif self.zoom_transform.xx >= 16:
scale = min(scale, 1)
# move the origin to point
- self.transform.translate(point[0], point[1])
+ self.zoom_transform.translate(event.x, event.y)
# scale from new origin
- self.transform.scale(scale, scale)
+ self.zoom_transform.scale(scale, scale)
# move back
- self.transform.translate(-point[0], -point[1])
+ self.zoom_transform.translate(-event.x, -event.y)
# snap to the edge when near 1x scaling
- if 0.99 < self.transform.xx < 1.01 and -50 < self.transform.x0 < 50:
- self.transform.x0 = 0
- self.transform.y0 = 0
+ if 0.99 < self.zoom_transform.xx < 1.01 and -50 < self.zoom_transform.x0 < 50:
+ self.zoom_transform.x0 = 0
+ self.zoom_transform.y0 = 0
print("snap")
self.queue_draw()
diff --git a/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h b/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h
index 04d93c4..d6e8f15 100644
--- a/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h
+++ b/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h
@@ -126,6 +126,8 @@
void TriggerEstimatorError() { profiled_subsystem_.TriggerEstimatorError(); }
+ void Estop() { state_ = State::ESTOP; }
+
void set_controller_index(int index) {
profiled_subsystem_.set_controller_index(index);
}
diff --git a/frc971/raspi/rootfs/change_hostname.sh b/frc971/raspi/rootfs/change_hostname.sh
index f555048..20ff635 100755
--- a/frc971/raspi/rootfs/change_hostname.sh
+++ b/frc971/raspi/rootfs/change_hostname.sh
@@ -52,7 +52,7 @@
# Put corret team number in imu's address, or add it if missing
if grep '^10\.[0-9]*\.[0-9]*\.105\s.*\s*imu$' /etc/hosts >/dev/null;
then
- sed -i "s/^10\.[0-9]*\.[0-9]*\(\.105\s.*imu\)$/${IP_BASE}\1/" /etc/hosts
+ sed -i "s/^10\.[0-9]*\.[0-9]*\(\.[0-9]*\s*pi-\)[0-9]*\(-[0-9] pi5 imu\)$/${IP_BASE}\1${TEAM_NUMBER}\2/" /etc/hosts
else
if grep '^10\.[0-9]*\.[0-9]*\.105\s*pi-[0-9]*-[0-9]*\s*pi5$' /etc/hosts
then
diff --git a/frc971/raspi/rootfs/target_configure.sh b/frc971/raspi/rootfs/target_configure.sh
index 388d291..06f481b 100755
--- a/frc971/raspi/rootfs/target_configure.sh
+++ b/frc971/raspi/rootfs/target_configure.sh
@@ -3,6 +3,7 @@
set -ex
mkdir -p /root/bin
+mkdir -p /home/pi/bin
# Give it a static IP
cp /tmp/dhcpcd.conf /etc/
diff --git a/frc971/wpilib/ahal/AnalogInput.cc b/frc971/wpilib/ahal/AnalogInput.cc
index 8d814ad..7482476 100644
--- a/frc971/wpilib/ahal/AnalogInput.cc
+++ b/frc971/wpilib/ahal/AnalogInput.cc
@@ -41,6 +41,8 @@
HAL_GetErrorMessage(status));
m_channel = std::numeric_limits<int>::max();
m_port = HAL_kInvalidHandle;
+ HAL_CHECK_STATUS(status)
+ << ": Failed to make AnalogInput channel " << channel;
return;
}
@@ -69,6 +71,7 @@
int32_t status = 0;
int value = HAL_GetAnalogValue(m_port, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
return value;
}
@@ -91,6 +94,7 @@
int32_t status = 0;
int value = HAL_GetAnalogAverageValue(m_port, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
return value;
}
@@ -107,6 +111,7 @@
int32_t status = 0;
double voltage = HAL_GetAnalogVoltage(m_port, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
return voltage;
}
@@ -129,6 +134,7 @@
int32_t status = 0;
double voltage = HAL_GetAnalogAverageVoltage(m_port, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
return voltage;
}
@@ -144,6 +150,7 @@
int32_t status = 0;
int lsbWeight = HAL_GetAnalogLSBWeight(m_port, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
return lsbWeight;
}
@@ -159,6 +166,7 @@
int32_t status = 0;
int offset = HAL_GetAnalogOffset(m_port, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
return offset;
}
@@ -188,6 +196,7 @@
int32_t status = 0;
HAL_SetAnalogAverageBits(m_port, bits, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
}
/**
@@ -202,6 +211,7 @@
int32_t status = 0;
int averageBits = HAL_GetAnalogAverageBits(m_port, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
return averageBits;
}
@@ -220,6 +230,7 @@
int32_t status = 0;
HAL_SetAnalogOversampleBits(m_port, bits, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
}
/**
@@ -236,6 +247,7 @@
int32_t status = 0;
int oversampleBits = HAL_GetAnalogOversampleBits(m_port, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
return oversampleBits;
}
@@ -251,6 +263,7 @@
int32_t status = 0;
HAL_SetAnalogSampleRate(samplesPerSecond, &status);
wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
}
/**
@@ -262,5 +275,6 @@
int32_t status = 0;
double sampleRate = HAL_GetAnalogSampleRate(&status);
wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
return sampleRate;
}
diff --git a/frc971/wpilib/ahal/AnalogTrigger.cc b/frc971/wpilib/ahal/AnalogTrigger.cc
index 825a655..bd63189 100644
--- a/frc971/wpilib/ahal/AnalogTrigger.cc
+++ b/frc971/wpilib/ahal/AnalogTrigger.cc
@@ -32,6 +32,7 @@
if (status != 0) {
wpi_setHALError(status);
m_trigger = HAL_kInvalidHandle;
+ HAL_CHECK_STATUS(status);
return;
}
int index = GetIndex();
@@ -46,6 +47,7 @@
if (status != 0) {
wpi_setHALError(status);
m_trigger = HAL_kInvalidHandle;
+ HAL_CHECK_STATUS(status);
return;
}
int index = GetIndex();
@@ -56,6 +58,7 @@
AnalogTrigger::~AnalogTrigger() {
int32_t status = 0;
HAL_CleanAnalogTrigger(m_trigger, &status);
+ HAL_CHECK_STATUS(status);
if (m_ownsAnalog) {
delete m_analogInput;
@@ -83,6 +86,7 @@
int32_t status = 0;
HAL_SetAnalogTriggerLimitsVoltage(m_trigger, lower, upper, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void AnalogTrigger::SetLimitsDutyCycle(double lower, double upper) {
@@ -90,6 +94,7 @@
int32_t status = 0;
HAL_SetAnalogTriggerLimitsDutyCycle(m_trigger, lower, upper, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void AnalogTrigger::SetLimitsRaw(int lower, int upper) {
@@ -97,6 +102,7 @@
int32_t status = 0;
HAL_SetAnalogTriggerLimitsRaw(m_trigger, lower, upper, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void AnalogTrigger::SetAveraged(bool useAveragedValue) {
@@ -104,6 +110,7 @@
int32_t status = 0;
HAL_SetAnalogTriggerAveraged(m_trigger, useAveragedValue, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void AnalogTrigger::SetFiltered(bool useFilteredValue) {
@@ -111,6 +118,7 @@
int32_t status = 0;
HAL_SetAnalogTriggerFiltered(m_trigger, useFilteredValue, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
int AnalogTrigger::GetIndex() const {
@@ -118,6 +126,7 @@
int32_t status = 0;
auto ret = HAL_GetAnalogTriggerFPGAIndex(m_trigger, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
return ret;
}
@@ -126,6 +135,7 @@
int32_t status = 0;
bool result = HAL_GetAnalogTriggerInWindow(m_trigger, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
return result;
}
@@ -134,6 +144,7 @@
int32_t status = 0;
bool result = HAL_GetAnalogTriggerTriggerState(m_trigger, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
return result;
}
diff --git a/frc971/wpilib/ahal/Counter.cc b/frc971/wpilib/ahal/Counter.cc
index 81e2c61..8e91c82 100644
--- a/frc971/wpilib/ahal/Counter.cc
+++ b/frc971/wpilib/ahal/Counter.cc
@@ -19,6 +19,7 @@
int32_t status = 0;
m_counter = HAL_InitializeCounter((HAL_Counter_Mode)mode, &m_index, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
SetMaxPeriod(0.5);
@@ -77,6 +78,7 @@
}
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
SetDownSourceEdge(inverted, true);
}
@@ -86,6 +88,7 @@
int32_t status = 0;
HAL_FreeCounter(m_counter, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void Counter::SetUpSource(int channel) {
@@ -119,6 +122,7 @@
m_counter, source->GetPortHandleForRouting(),
(HAL_AnalogTriggerType)source->GetAnalogTriggerTypeForRouting(), &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void Counter::SetUpSource(DigitalSource& source) {
@@ -136,6 +140,7 @@
int32_t status = 0;
HAL_SetCounterUpSourceEdge(m_counter, risingEdge, fallingEdge, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void Counter::ClearUpSource() {
@@ -144,6 +149,7 @@
int32_t status = 0;
HAL_ClearCounterUpSource(m_counter, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void Counter::SetDownSource(int channel) {
@@ -182,6 +188,7 @@
m_counter, source->GetPortHandleForRouting(),
(HAL_AnalogTriggerType)source->GetAnalogTriggerTypeForRouting(), &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void Counter::SetDownSourceEdge(bool risingEdge, bool fallingEdge) {
@@ -194,6 +201,7 @@
int32_t status = 0;
HAL_SetCounterDownSourceEdge(m_counter, risingEdge, fallingEdge, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void Counter::ClearDownSource() {
@@ -202,6 +210,7 @@
int32_t status = 0;
HAL_ClearCounterDownSource(m_counter, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void Counter::SetUpDownCounterMode() {
@@ -209,6 +218,7 @@
int32_t status = 0;
HAL_SetCounterUpDownMode(m_counter, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void Counter::SetExternalDirectionMode() {
@@ -216,6 +226,7 @@
int32_t status = 0;
HAL_SetCounterExternalDirectionMode(m_counter, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void Counter::SetSemiPeriodMode(bool highSemiPeriod) {
@@ -223,6 +234,7 @@
int32_t status = 0;
HAL_SetCounterSemiPeriodMode(m_counter, highSemiPeriod, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void Counter::SetPulseLengthMode(double threshold) {
@@ -230,6 +242,7 @@
int32_t status = 0;
HAL_SetCounterPulseLengthMode(m_counter, threshold, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void Counter::SetReverseDirection(bool reverseDirection) {
@@ -237,6 +250,7 @@
int32_t status = 0;
HAL_SetCounterReverseDirection(m_counter, reverseDirection, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void Counter::SetSamplesToAverage(int samplesToAverage) {
@@ -248,12 +262,14 @@
int32_t status = 0;
HAL_SetCounterSamplesToAverage(m_counter, samplesToAverage, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
int Counter::GetSamplesToAverage() const {
int32_t status = 0;
int samples = HAL_GetCounterSamplesToAverage(m_counter, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
return samples;
}
@@ -264,6 +280,7 @@
int32_t status = 0;
int value = HAL_GetCounter(m_counter, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
return value;
}
@@ -272,6 +289,7 @@
int32_t status = 0;
HAL_ResetCounter(m_counter, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
double Counter::GetPeriod() const {
@@ -279,6 +297,7 @@
int32_t status = 0;
double value = HAL_GetCounterPeriod(m_counter, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
return value;
}
@@ -287,6 +306,7 @@
int32_t status = 0;
HAL_SetCounterMaxPeriod(m_counter, maxPeriod, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
void Counter::SetUpdateWhenEmpty(bool enabled) {
@@ -294,6 +314,7 @@
int32_t status = 0;
HAL_SetCounterUpdateWhenEmpty(m_counter, enabled, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
}
bool Counter::GetStopped() const {
@@ -301,6 +322,7 @@
int32_t status = 0;
bool value = HAL_GetCounterStopped(m_counter, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
return value;
}
@@ -309,5 +331,6 @@
int32_t status = 0;
bool value = HAL_GetCounterDirection(m_counter, &status);
wpi_setHALError(status);
+ HAL_CHECK_STATUS(status);
return value;
}
diff --git a/frc971/wpilib/ahal/DigitalInput.cc b/frc971/wpilib/ahal/DigitalInput.cc
index 3e07208..d922cae 100644
--- a/frc971/wpilib/ahal/DigitalInput.cc
+++ b/frc971/wpilib/ahal/DigitalInput.cc
@@ -43,6 +43,7 @@
channel, HAL_GetErrorMessage(status));
m_handle = HAL_kInvalidHandle;
m_channel = std::numeric_limits<int>::max();
+ HAL_CHECK_STATUS(status) << ": Channel " << channel;
return;
}
@@ -72,6 +73,7 @@
int32_t status = 0;
bool value = HAL_GetDIO(m_handle, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
return value;
}
diff --git a/frc971/wpilib/ahal/DigitalOutput.cc b/frc971/wpilib/ahal/DigitalOutput.cc
index cc1f3d2..ac00df3 100644
--- a/frc971/wpilib/ahal/DigitalOutput.cc
+++ b/frc971/wpilib/ahal/DigitalOutput.cc
@@ -43,6 +43,7 @@
if (status != 0) {
wpi_setErrorWithContextRange(status, 0, HAL_GetNumDigitalChannels(),
channel, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
m_channel = std::numeric_limits<int>::max();
m_handle = HAL_kInvalidHandle;
return;
@@ -75,6 +76,7 @@
int32_t status = 0;
HAL_SetDIO(m_handle, value, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
}
/**
@@ -88,6 +90,7 @@
int32_t status = 0;
bool val = HAL_GetDIO(m_handle, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
return val;
}
@@ -110,6 +113,7 @@
int32_t status = 0;
HAL_Pulse(m_handle, length, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
}
/**
@@ -123,6 +127,7 @@
int32_t status = 0;
bool value = HAL_IsPulsing(m_handle, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
return value;
}
@@ -142,6 +147,7 @@
int32_t status = 0;
HAL_SetDigitalPWMRate(rate, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+ HAL_CHECK_STATUS(status);
}
/**
@@ -173,6 +179,8 @@
if (StatusIsFatal()) return;
HAL_SetDigitalPWMOutputChannel(m_pwmGenerator, m_channel, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ HAL_CHECK_STATUS(status);
}
/**
@@ -194,6 +202,8 @@
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
m_pwmGenerator = HAL_kInvalidHandle;
+
+ HAL_CHECK_STATUS(status);
}
/**
@@ -210,6 +220,8 @@
int32_t status = 0;
HAL_SetDigitalPWMDutyCycle(m_pwmGenerator, dutyCycle, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
+
+ HAL_CHECK_STATUS(status);
}
/**
diff --git a/frc971/wpilib/ahal/Encoder.cc b/frc971/wpilib/ahal/Encoder.cc
index b452720..417792d 100644
--- a/frc971/wpilib/ahal/Encoder.cc
+++ b/frc971/wpilib/ahal/Encoder.cc
@@ -9,11 +9,10 @@
#include "hal/HAL.h"
#include "frc971/wpilib/ahal/DigitalInput.h"
+#include "frc971/wpilib/ahal/WPIErrors.h"
using namespace frc;
-#define HAL_FATAL_WITH_STATUS(status)
-
/**
* Common initialization code for Encoders.
*
@@ -40,7 +39,7 @@
m_bSource->GetPortHandleForRouting(),
(HAL_AnalogTriggerType)m_bSource->GetAnalogTriggerTypeForRouting(),
reverseDirection, (HAL_EncoderEncodingType)encodingType, &status);
- HAL_FATAL_WITH_STATUS(status);
+ HAL_CHECK_STATUS(status);
HAL_Report(HALUsageReporting::kResourceType_Encoder, GetFPGAIndex(),
encodingType);
@@ -84,7 +83,7 @@
Encoder::~Encoder() {
int32_t status = 0;
HAL_FreeEncoder(m_encoder, &status);
- HAL_FATAL_WITH_STATUS(status);
+ HAL_CHECK_STATUS(status);
}
/**
@@ -110,7 +109,7 @@
int Encoder::GetRaw() const {
int32_t status = 0;
int value = HAL_GetEncoderRaw(m_encoder, &status);
- HAL_FATAL_WITH_STATUS(status);
+ HAL_CHECK_STATUS(status);
return value;
}
@@ -129,7 +128,7 @@
double Encoder::GetPeriod() const {
int32_t status = 0;
double value = HAL_GetEncoderPeriod(m_encoder, &status);
- HAL_FATAL_WITH_STATUS(status);
+ HAL_CHECK_STATUS(status);
return value;
}
/**
@@ -151,12 +150,12 @@
void Encoder::SetMaxPeriod(double maxPeriod) {
int32_t status = 0;
HAL_SetEncoderMaxPeriod(m_encoder, maxPeriod, &status);
- HAL_FATAL_WITH_STATUS(status);
+ HAL_CHECK_STATUS(status);
}
int Encoder::GetFPGAIndex() const {
int32_t status = 0;
int val = HAL_GetEncoderFPGAIndex(m_encoder, &status);
- HAL_FATAL_WITH_STATUS(status);
+ HAL_CHECK_STATUS(status);
return val;
}
diff --git a/frc971/wpilib/ahal/PWM.cc b/frc971/wpilib/ahal/PWM.cc
index 31b9863..7184643 100644
--- a/frc971/wpilib/ahal/PWM.cc
+++ b/frc971/wpilib/ahal/PWM.cc
@@ -17,8 +17,6 @@
using namespace frc;
-#define HAL_FATAL_ERROR()
-
/**
* Allocate a PWM given a channel number.
*
@@ -42,7 +40,7 @@
// wpi_setErrorWithContextRange(status, 0, HAL_GetNumPWMChannels(),
// channel,
// HAL_GetErrorMessage(status));
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status) << ": Channel " << channel;
m_channel = std::numeric_limits<int>::max();
m_handle = HAL_kInvalidHandle;
return;
@@ -51,10 +49,10 @@
m_channel = channel;
HAL_SetPWMDisabled(m_handle, &status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status) << ": Channel " << channel;
status = 0;
HAL_SetPWMEliminateDeadband(m_handle, false, &status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status) << ": Channel " << channel;
HAL_Report(HALUsageReporting::kResourceType_PWM, channel);
}
@@ -68,10 +66,10 @@
int32_t status = 0;
HAL_SetPWMDisabled(m_handle, &status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
HAL_FreePWMPort(m_handle, &status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
}
/**
@@ -85,7 +83,7 @@
void PWM::EnableDeadbandElimination(bool eliminateDeadband) {
int32_t status = 0;
HAL_SetPWMEliminateDeadband(m_handle, eliminateDeadband, &status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
}
/**
@@ -106,7 +104,7 @@
int32_t status = 0;
HAL_SetPWMConfig(m_handle, max, deadbandMax, center, deadbandMin, min,
&status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
}
/**
@@ -127,7 +125,7 @@
int32_t status = 0;
HAL_SetPWMConfigRaw(m_handle, max, deadbandMax, center, deadbandMin, min,
&status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
}
/**
@@ -148,7 +146,7 @@
int32_t status = 0;
HAL_GetPWMConfigRaw(m_handle, max, deadbandMax, center, deadbandMin, min,
&status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
}
/**
@@ -164,7 +162,7 @@
void PWM::SetPosition(double pos) {
int32_t status = 0;
HAL_SetPWMPosition(m_handle, pos, &status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
}
/**
@@ -180,7 +178,7 @@
double PWM::GetPosition() const {
int32_t status = 0;
double position = HAL_GetPWMPosition(m_handle, &status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
return position;
}
@@ -200,7 +198,7 @@
void PWM::SetSpeed(double speed) {
int32_t status = 0;
HAL_SetPWMSpeed(m_handle, speed, &status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
}
/**
@@ -218,7 +216,7 @@
double PWM::GetSpeed() const {
int32_t status = 0;
double speed = HAL_GetPWMSpeed(m_handle, &status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
return speed;
}
@@ -232,7 +230,7 @@
void PWM::SetRaw(uint16_t value) {
int32_t status = 0;
HAL_SetPWMRaw(m_handle, value, &status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
}
/**
@@ -245,7 +243,7 @@
uint16_t PWM::GetRaw() const {
int32_t status = 0;
uint16_t value = HAL_GetPWMRaw(m_handle, &status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
return value;
}
@@ -274,7 +272,7 @@
LOG(FATAL) << "Invalid multiplier " << mult;
}
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
}
/**
@@ -285,12 +283,12 @@
int32_t status = 0;
HAL_SetPWMDisabled(m_handle, &status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
}
void PWM::SetZeroLatch() {
int32_t status = 0;
HAL_LatchPWMZero(m_handle, &status);
- HAL_FATAL_ERROR();
+ HAL_CHECK_STATUS(status);
}
diff --git a/frc971/wpilib/ahal/WPIErrors.h b/frc971/wpilib/ahal/WPIErrors.h
index 482240c..601e65a 100644
--- a/frc971/wpilib/ahal/WPIErrors.h
+++ b/frc971/wpilib/ahal/WPIErrors.h
@@ -9,6 +9,8 @@
#include <cstdint>
+#include "glog/logging.h"
+
#ifdef WPI_ERRORS_DEFINE_STRINGS
#define S(label, offset, message) \
const char *wpi_error_s_##label = message; \
@@ -19,6 +21,9 @@
const int wpi_error_value_##label = offset
#endif
+#define HAL_CHECK_STATUS(status) \
+ CHECK(status == 0) << HAL_GetLastError(&(status))
+
/*
* Fatal errors
*/
diff --git a/package.json b/package.json
index 7e6885b..d16aed7 100644
--- a/package.json
+++ b/package.json
@@ -2,34 +2,37 @@
"name": "971-Robot-Code",
"license": "MIT",
"devDependencies": {
- "@types/jasmine": "latest",
- "@types/node": "latest",
- "jasmine": "latest",
- "karma-requirejs": "latest",
- "karma-sourcemap-loader": "latest",
- "karma-chrome-launcher": "latest",
- "karma-firefox-launcher": "latest",
- "karma": "latest",
- "karma-jasmine": "latest",
- "requirejs": "latest",
- "@bazel/concatjs": "latest",
- "@angular/animations": "latest",
- "@angular/core": "latest",
- "@angular/common": "latest",
- "@angular/platform-browser": "latest",
- "@angular/compiler": "latest",
- "@angular/compiler-cli": "latest",
- "@angular/cli": "latest",
- "@types/flatbuffers": "latest",
- "@bazel/typescript": "4.4.6",
- "@bazel/rollup": "latest",
- "@bazel/terser": "latest",
- "@rollup/plugin-node-resolve": "latest",
- "typescript": "latest",
- "rollup": "latest",
- "terser": "latest",
+ "@angular/animations": "13.2.0",
+ "@angular/common": "13.2.0",
+ "@angular/compiler": "13.2.0",
+ "@angular/compiler-cli": "13.2.0",
+ "@angular/core": "13.2.0",
+ "@angular/forms": "13.2.0",
+ "@angular/platform-browser": "13.2.0",
+ "@angular/cli": "13.2.0",
"@babel/cli": "^7.6.0",
"@babel/core": "^7.6.0",
+ "@bazel/concatjs": "4.4.6",
+ "@bazel/protractor": "4.4.6",
+ "@bazel/rollup": "4.4.6",
+ "@bazel/typescript": "4.4.6",
+ "@bazel/terser": "4.4.6",
+ "@types/jasmine": "3.10.3",
+ "jasmine": "3.10.0",
+ "karma": "6.3.12",
+ "karma-chrome-launcher": "3.1.0",
+ "karma-firefox-launcher": "2.1.2",
+ "karma-jasmine": "4.0.1",
+ "karma-requirejs": "1.1.0",
+ "karma-sourcemap-loader": "0.3.8",
+ "protractor": "7.0.0",
+ "requirejs": "2.3.6",
+ "rollup": "2.66.1",
+ "@rollup/plugin-node-resolve": "13.1.3",
+ "@types/flatbuffers": "1.10.0",
+ "@types/node": "17.0.21",
+ "typescript": "4.5.5",
+ "terser": "5.10.0",
"zone.js": "^0.11.4"
}
}
diff --git a/scouting/BUILD b/scouting/BUILD
index 9b8adee..0ed540b 100644
--- a/scouting/BUILD
+++ b/scouting/BUILD
@@ -1,5 +1,5 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
-load("//tools/build_rules:js.bzl", "turn_files_into_runfiles")
+load("//tools/build_rules:js.bzl", "protractor_ts_test", "turn_files_into_runfiles")
go_binary(
name = "sql_demo",
@@ -35,12 +35,11 @@
],
)
-py_test(
+protractor_ts_test(
name = "scouting_test",
srcs = [
- "scouting_test.py",
+ ":scouting_test.ts",
],
- data = [
- ":scouting",
- ],
+ on_prepare = ":scouting_test.protractor.on-prepare.js",
+ server = ":scouting",
)
diff --git a/scouting/db/db.go b/scouting/db/db.go
index 1d0081b..5d68e0f 100644
--- a/scouting/db/db.go
+++ b/scouting/db/db.go
@@ -12,18 +12,18 @@
}
type Match struct {
- matchNumber, round int
- compLevel string
- r1, r2, r3, b1, b2, b3 int
+ MatchNumber, Round int32
+ CompLevel string
+ R1, R2, R3, B1, B2, B3 int32
// Each of these variables holds the matchID of the corresponding Stats row
r1ID, r2ID, r3ID, b1ID, b2ID, b3ID int
}
type Stats struct {
- teamNumber, matchNumber int
- shotsMissed, upperGoalShots, lowerGoalShots int
- shotsMissedAuto, upperGoalAuto, lowerGoalAuto, playedDefense int
- climbing int
+ TeamNumber, MatchNumber int32
+ ShotsMissed, UpperGoalShots, LowerGoalShots int32
+ ShotsMissedAuto, UpperGoalAuto, LowerGoalAuto, PlayedDefense int32
+ Climbing int32
}
// Opens a database at the specified path. If the path refers to a non-existent
@@ -32,14 +32,14 @@
database := new(Database)
database.DB, _ = sql.Open("sqlite3", path)
statement, error_ := database.Prepare("CREATE TABLE IF NOT EXISTS matches " +
- "(id INTEGER PRIMARY KEY, matchNumber INTEGER, round INTEGER, compLevel INTEGER, r1 INTEGER, r2 INTEGER, r3 INTEGER, b1 INTEGER, b2 INTEGER, b3 INTEGER, r1ID INTEGER, r2ID INTEGER, r3ID INTEGER, b1ID INTEGER, b2ID INTEGER, b3ID INTEGER)")
+ "(id INTEGER PRIMARY KEY, MatchNumber INTEGER, Round INTEGER, CompLevel INTEGER, R1 INTEGER, R2 INTEGER, R3 INTEGER, B1 INTEGER, B2 INTEGER, B3 INTEGER, r1ID INTEGER, r2ID INTEGER, r3ID INTEGER, b1ID INTEGER, b2ID INTEGER, b3ID INTEGER)")
defer statement.Close()
if error_ != nil {
fmt.Println(error_)
return nil, error_
}
_, error_ = statement.Exec()
- statement, error_ = database.Prepare("CREATE TABLE IF NOT EXISTS team_match_stats (id INTEGER PRIMARY KEY, teamNumber INTEGER, matchNumber DOUBLE, shotsMissed INTEGER, upperGoalShots INTEGER, lowerGoalShots INTEGER, shotsMissedAuto INTEGER, upperGoalAuto INTEGER, lowerGoalAuto INTEGER, playedDefense INTEGER, climbing INTEGER)")
+ statement, error_ = database.Prepare("CREATE TABLE IF NOT EXISTS team_match_stats (id INTEGER PRIMARY KEY, TeamNumber INTEGER, MatchNumber DOUBLE, ShotsMissed INTEGER, UpperGoalShots INTEGER, LowerGoalShots INTEGER, ShotsMissedAuto INTEGER, UpperGoalAuto INTEGER, LowerGoalAuto INTEGER, PlayedDefense INTEGER, Climbing INTEGER)")
defer statement.Close()
if error_ != nil {
fmt.Println(error_)
@@ -67,28 +67,28 @@
// This function will also populate the Stats table with six empty rows every time a match is added
func (database *Database) AddToMatch(m Match) error {
- statement, error_ := database.Prepare("INSERT INTO team_match_stats(teamNumber, matchNumber, shotsMissed, upperGoalShots, lowerGoalShots, shotsMissedAuto, upperGoalAuto, lowerGoalAuto, playedDefense, climbing) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
+ statement, error_ := database.Prepare("INSERT INTO team_match_stats(TeamNumber, MatchNumber, ShotsMissed, UpperGoalShots, LowerGoalShots, ShotsMissedAuto, UpperGoalAuto, LowerGoalAuto, PlayedDefense, Climbing) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
defer statement.Close()
if error_ != nil {
fmt.Println("failed to prepare stats database:", error_)
return (error_)
}
var rowIds [6]int64
- for i, teamNumber := range []int{m.r1, m.r2, m.r3, m.b1, m.b2, m.b3} {
- result, error_ := statement.Exec(teamNumber, m.matchNumber, 0, 0, 0, 0, 0, 0, 0, 0)
+ for i, TeamNumber := range []int32{m.R1, m.R2, m.R3, m.B1, m.B2, m.B3} {
+ result, error_ := statement.Exec(TeamNumber, m.MatchNumber, 0, 0, 0, 0, 0, 0, 0, 0)
if error_ != nil {
fmt.Println("failed to execute statement 2:", error_)
return (error_)
}
rowIds[i], error_ = result.LastInsertId()
}
- statement, error_ = database.Prepare("INSERT INTO matches(matchNumber, round, compLevel, r1, r2, r3, b1, b2, b3, r1ID, r2ID, r3ID, b1ID, b2ID, b3ID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
+ statement, error_ = database.Prepare("INSERT INTO matches(MatchNumber, Round, CompLevel, R1, R2, R3, B1, B2, B3, r1ID, r2ID, r3ID, b1ID, b2ID, b3ID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
defer statement.Close()
if error_ != nil {
fmt.Println("failed to prepare match database:", error_)
return (error_)
}
- _, error_ = statement.Exec(m.matchNumber, m.round, m.compLevel, m.r1, m.r2, m.r3, m.b1, m.b2, m.b3, rowIds[0], rowIds[1], rowIds[2], rowIds[3], rowIds[4], rowIds[5])
+ _, error_ = statement.Exec(m.MatchNumber, m.Round, m.CompLevel, m.R1, m.R2, m.R3, m.B1, m.B2, m.B3, rowIds[0], rowIds[1], rowIds[2], rowIds[3], rowIds[4], rowIds[5])
if error_ != nil {
fmt.Println(error_)
return (error_)
@@ -97,12 +97,12 @@
}
func (database *Database) AddToStats(s Stats) error {
- statement, error_ := database.Prepare("UPDATE team_match_stats SET teamNumber = ?, matchNumber = ?, shotsMissed = ?, upperGoalShots = ?, lowerGoalShots = ?, shotsMissedAuto = ?, upperGoalAuto = ?, lowerGoalAuto = ?, playedDefense = ?, climbing = ? WHERE matchNumber = ? AND teamNumber = ?")
+ statement, error_ := database.Prepare("UPDATE team_match_stats SET TeamNumber = ?, MatchNumber = ?, ShotsMissed = ?, UpperGoalShots = ?, LowerGoalShots = ?, ShotsMissedAuto = ?, UpperGoalAuto = ?, LowerGoalAuto = ?, PlayedDefense = ?, Climbing = ? WHERE MatchNumber = ? AND TeamNumber = ?")
if error_ != nil {
fmt.Println(error_)
return (error_)
}
- _, error_ = statement.Exec(s.teamNumber, s.matchNumber, s.shotsMissed, s.upperGoalShots, s.lowerGoalShots, s.shotsMissedAuto, s.upperGoalAuto, s.lowerGoalAuto, s.playedDefense, s.climbing, s.matchNumber, s.teamNumber)
+ _, error_ = statement.Exec(s.TeamNumber, s.MatchNumber, s.ShotsMissed, s.UpperGoalShots, s.LowerGoalShots, s.ShotsMissedAuto, s.UpperGoalAuto, s.LowerGoalAuto, s.PlayedDefense, s.Climbing, s.MatchNumber, s.TeamNumber)
if error_ != nil {
fmt.Println(error_)
return (error_)
@@ -117,7 +117,7 @@
for rows.Next() {
var match Match
var id int
- error_ := rows.Scan(&id, &match.matchNumber, &match.round, &match.compLevel, &match.r1, &match.r2, &match.r3, &match.b1, &match.b2, &match.b3, &match.r1ID, &match.r2ID, &match.r3ID, &match.b1ID, &match.b2ID, &match.b3ID)
+ error_ := rows.Scan(&id, &match.MatchNumber, &match.Round, &match.CompLevel, &match.R1, &match.R2, &match.R3, &match.B1, &match.B2, &match.B3, &match.r1ID, &match.r2ID, &match.r3ID, &match.b1ID, &match.b2ID, &match.b3ID)
if error_ != nil {
fmt.Println(nil, error_)
return nil, error_
@@ -134,7 +134,7 @@
var id int
for rows.Next() {
var team Stats
- error_ := rows.Scan(&id, &team.teamNumber, &team.matchNumber, &team.shotsMissed, &team.upperGoalShots, &team.lowerGoalShots, &team.shotsMissedAuto, &team.upperGoalAuto, &team.lowerGoalAuto, &team.playedDefense, &team.climbing)
+ error_ := rows.Scan(&id, &team.TeamNumber, &team.MatchNumber, &team.ShotsMissed, &team.UpperGoalShots, &team.LowerGoalShots, &team.ShotsMissedAuto, &team.UpperGoalAuto, &team.LowerGoalAuto, &team.PlayedDefense, &team.Climbing)
if error_ != nil {
fmt.Println(error_)
return nil, error_
@@ -144,8 +144,8 @@
return teams, nil
}
-func (database *Database) QueryMatches(teamNumber_ int) ([]Match, error) {
- rows, error_ := database.Query("SELECT * FROM matches WHERE r1 = ? OR r2 = ? OR r3 = ? OR b1 = ? OR b2 = ? OR b3 = ?", teamNumber_, teamNumber_, teamNumber_, teamNumber_, teamNumber_, teamNumber_)
+func (database *Database) QueryMatches(teamNumber_ int32) ([]Match, error) {
+ rows, error_ := database.Query("SELECT * FROM matches WHERE R1 = ? OR R2 = ? OR R3 = ? OR B1 = ? OR B2 = ? OR B3 = ?", teamNumber_, teamNumber_, teamNumber_, teamNumber_, teamNumber_, teamNumber_)
if error_ != nil {
fmt.Println("failed to execute statement 1:", error_)
return nil, error_
@@ -155,14 +155,14 @@
var id int
for rows.Next() {
var match Match
- rows.Scan(&id, &match.matchNumber, &match.round, &match.compLevel, &match.r1, &match.r2, &match.r3, &match.b1, &match.b2, &match.b3, &match.r1ID, &match.r2ID, &match.r3ID, &match.b1ID, &match.b2ID, &match.b3ID)
+ rows.Scan(&id, &match.MatchNumber, &match.Round, &match.CompLevel, &match.R1, &match.R2, &match.R3, &match.B1, &match.B2, &match.B3, &match.r1ID, &match.r2ID, &match.r3ID, &match.b1ID, &match.b2ID, &match.b3ID)
matches = append(matches, match)
}
return matches, nil
}
func (database *Database) QueryStats(teamNumber_ int) ([]Stats, error) {
- rows, error_ := database.Query("SELECT * FROM team_match_stats WHERE teamNumber = ?", teamNumber_)
+ rows, error_ := database.Query("SELECT * FROM team_match_stats WHERE TeamNumber = ?", teamNumber_)
if error_ != nil {
fmt.Println("failed to execute statement 3:", error_)
return nil, error_
@@ -172,9 +172,9 @@
for rows.Next() {
var team Stats
var id int
- error_ = rows.Scan(&id, &team.teamNumber, &team.matchNumber, &team.shotsMissed,
- &team.upperGoalShots, &team.lowerGoalShots, &team.shotsMissedAuto, &team.upperGoalAuto,
- &team.lowerGoalAuto, &team.playedDefense, &team.climbing)
+ error_ = rows.Scan(&id, &team.TeamNumber, &team.MatchNumber, &team.ShotsMissed,
+ &team.UpperGoalShots, &team.LowerGoalShots, &team.ShotsMissedAuto, &team.UpperGoalAuto,
+ &team.LowerGoalAuto, &team.PlayedDefense, &team.Climbing)
teams = append(teams, team)
}
if error_ != nil {
diff --git a/scouting/db/db_test.go b/scouting/db/db_test.go
index 39f12e3..85ad339 100644
--- a/scouting/db/db_test.go
+++ b/scouting/db/db_test.go
@@ -23,7 +23,7 @@
db := createDatabase(t)
defer db.Delete()
- correct := []Match{Match{matchNumber: 7, round: 1, compLevel: "quals", r1: 9999, r2: 1000, r3: 777, b1: 0000, b2: 4321, b3: 1234, r1ID: 1, r2ID: 2, r3ID: 3, b1ID: 4, b2ID: 5, b3ID: 6}}
+ correct := []Match{Match{MatchNumber: 7, Round: 1, CompLevel: "quals", R1: 9999, R2: 1000, R3: 777, B1: 0000, B2: 4321, B3: 1234, r1ID: 1, r2ID: 2, r3ID: 3, b1ID: 4, b2ID: 5, b3ID: 6}}
db.AddToMatch(correct[0])
got, error_ := db.ReturnMatches()
if error_ != nil {
@@ -39,14 +39,14 @@
defer db.Delete()
correct := []Stats{
- Stats{teamNumber: 1236, matchNumber: 7, shotsMissed: 9, upperGoalShots: 5, lowerGoalShots: 4, shotsMissedAuto: 3, upperGoalAuto: 2, lowerGoalAuto: 1, playedDefense: 2, climbing: 3},
- Stats{teamNumber: 1001, matchNumber: 7, shotsMissed: 6, upperGoalShots: 9, lowerGoalShots: 9, shotsMissedAuto: 0, upperGoalAuto: 0, lowerGoalAuto: 0, playedDefense: 0, climbing: 0},
- Stats{teamNumber: 777, matchNumber: 7, shotsMissed: 5, upperGoalShots: 7, lowerGoalShots: 12, shotsMissedAuto: 0, upperGoalAuto: 4, lowerGoalAuto: 0, playedDefense: 0, climbing: 0},
- Stats{teamNumber: 1000, matchNumber: 7, shotsMissed: 12, upperGoalShots: 6, lowerGoalShots: 10, shotsMissedAuto: 0, upperGoalAuto: 7, lowerGoalAuto: 0, playedDefense: 0, climbing: 0},
- Stats{teamNumber: 4321, matchNumber: 7, shotsMissed: 14, upperGoalShots: 12, lowerGoalShots: 3, shotsMissedAuto: 0, upperGoalAuto: 7, lowerGoalAuto: 0, playedDefense: 0, climbing: 0},
- Stats{teamNumber: 1234, matchNumber: 7, shotsMissed: 3, upperGoalShots: 4, lowerGoalShots: 0, shotsMissedAuto: 0, upperGoalAuto: 9, lowerGoalAuto: 0, playedDefense: 0, climbing: 0},
+ Stats{TeamNumber: 1236, MatchNumber: 7, ShotsMissed: 9, UpperGoalShots: 5, LowerGoalShots: 4, ShotsMissedAuto: 3, UpperGoalAuto: 2, LowerGoalAuto: 1, PlayedDefense: 2, Climbing: 3},
+ Stats{TeamNumber: 1001, MatchNumber: 7, ShotsMissed: 6, UpperGoalShots: 9, LowerGoalShots: 9, ShotsMissedAuto: 0, UpperGoalAuto: 0, LowerGoalAuto: 0, PlayedDefense: 0, Climbing: 0},
+ Stats{TeamNumber: 777, MatchNumber: 7, ShotsMissed: 5, UpperGoalShots: 7, LowerGoalShots: 12, ShotsMissedAuto: 0, UpperGoalAuto: 4, LowerGoalAuto: 0, PlayedDefense: 0, Climbing: 0},
+ Stats{TeamNumber: 1000, MatchNumber: 7, ShotsMissed: 12, UpperGoalShots: 6, LowerGoalShots: 10, ShotsMissedAuto: 0, UpperGoalAuto: 7, LowerGoalAuto: 0, PlayedDefense: 0, Climbing: 0},
+ Stats{TeamNumber: 4321, MatchNumber: 7, ShotsMissed: 14, UpperGoalShots: 12, LowerGoalShots: 3, ShotsMissedAuto: 0, UpperGoalAuto: 7, LowerGoalAuto: 0, PlayedDefense: 0, Climbing: 0},
+ Stats{TeamNumber: 1234, MatchNumber: 7, ShotsMissed: 3, UpperGoalShots: 4, LowerGoalShots: 0, ShotsMissedAuto: 0, UpperGoalAuto: 9, LowerGoalAuto: 0, PlayedDefense: 0, Climbing: 0},
}
- db.AddToMatch(Match{matchNumber: 7, round: 1, compLevel: "quals", r1: 1236, r2: 1001, r3: 777, b1: 1000, b2: 4321, b3: 1234, r1ID: 1, r2ID: 2, r3ID: 3, b1ID: 4, b2ID: 5, b3ID: 6})
+ db.AddToMatch(Match{MatchNumber: 7, Round: 1, CompLevel: "quals", R1: 1236, R2: 1001, R3: 777, B1: 1000, B2: 4321, B3: 1234, r1ID: 1, r2ID: 2, r3ID: 3, b1ID: 4, b2ID: 5, b3ID: 6})
for i := 0; i < len(correct); i++ {
db.AddToStats(correct[i])
}
@@ -64,10 +64,10 @@
defer db.Delete()
testDatabase := []Match{
- Match{matchNumber: 2, round: 1, compLevel: "quals", r1: 251, r2: 169, r3: 286, b1: 253, b2: 538, b3: 149},
- Match{matchNumber: 4, round: 1, compLevel: "quals", r1: 198, r2: 135, r3: 777, b1: 999, b2: 434, b3: 698},
- Match{matchNumber: 3, round: 1, compLevel: "quals", r1: 147, r2: 421, r3: 538, b1: 126, b2: 448, b3: 262},
- Match{matchNumber: 6, round: 1, compLevel: "quals", r1: 191, r2: 132, r3: 773, b1: 994, b2: 435, b3: 696},
+ Match{MatchNumber: 2, Round: 1, CompLevel: "quals", R1: 251, R2: 169, R3: 286, B1: 253, B2: 538, B3: 149},
+ Match{MatchNumber: 4, Round: 1, CompLevel: "quals", R1: 198, R2: 135, R3: 777, B1: 999, B2: 434, B3: 698},
+ Match{MatchNumber: 3, Round: 1, CompLevel: "quals", R1: 147, R2: 421, R3: 538, B1: 126, B2: 448, B3: 262},
+ Match{MatchNumber: 6, Round: 1, CompLevel: "quals", R1: 191, R2: 132, R3: 773, B1: 994, B2: 435, B3: 696},
}
for i := 0; i < len(testDatabase); i++ {
@@ -75,8 +75,8 @@
}
correct := []Match{
- Match{matchNumber: 2, round: 1, compLevel: "quals", r1: 251, r2: 169, r3: 286, b1: 253, b2: 538, b3: 149, r1ID: 1, r2ID: 2, r3ID: 3, b1ID: 4, b2ID: 5, b3ID: 6},
- Match{matchNumber: 3, round: 1, compLevel: "quals", r1: 147, r2: 421, r3: 538, b1: 126, b2: 448, b3: 262, r1ID: 13, r2ID: 14, r3ID: 15, b1ID: 16, b2ID: 17, b3ID: 18},
+ Match{MatchNumber: 2, Round: 1, CompLevel: "quals", R1: 251, R2: 169, R3: 286, B1: 253, B2: 538, B3: 149, r1ID: 1, r2ID: 2, r3ID: 3, b1ID: 4, b2ID: 5, b3ID: 6},
+ Match{MatchNumber: 3, Round: 1, CompLevel: "quals", R1: 147, R2: 421, R3: 538, B1: 126, B2: 448, B3: 262, r1ID: 13, r2ID: 14, r3ID: 15, b1ID: 16, b2ID: 17, b3ID: 18},
}
got, error_ := db.QueryMatches(538)
@@ -93,19 +93,19 @@
defer db.Delete()
testDatabase := []Stats{
- Stats{teamNumber: 1235, matchNumber: 94, shotsMissed: 2, upperGoalShots: 2, lowerGoalShots: 2, shotsMissedAuto: 2, upperGoalAuto: 2, lowerGoalAuto: 2, playedDefense: 2, climbing: 2},
- Stats{teamNumber: 1234, matchNumber: 94, shotsMissed: 4, upperGoalShots: 4, lowerGoalShots: 4, shotsMissedAuto: 4, upperGoalAuto: 4, lowerGoalAuto: 4, playedDefense: 7, climbing: 2},
- Stats{teamNumber: 1233, matchNumber: 94, shotsMissed: 3, upperGoalShots: 3, lowerGoalShots: 3, shotsMissedAuto: 3, upperGoalAuto: 3, lowerGoalAuto: 3, playedDefense: 3, climbing: 3},
- Stats{teamNumber: 1232, matchNumber: 94, shotsMissed: 5, upperGoalShots: 5, lowerGoalShots: 5, shotsMissedAuto: 5, upperGoalAuto: 5, lowerGoalAuto: 5, playedDefense: 7, climbing: 1},
- Stats{teamNumber: 1231, matchNumber: 94, shotsMissed: 6, upperGoalShots: 6, lowerGoalShots: 6, shotsMissedAuto: 6, upperGoalAuto: 6, lowerGoalAuto: 6, playedDefense: 7, climbing: 1},
- Stats{teamNumber: 1239, matchNumber: 94, shotsMissed: 7, upperGoalShots: 7, lowerGoalShots: 7, shotsMissedAuto: 7, upperGoalAuto: 7, lowerGoalAuto: 3, playedDefense: 7, climbing: 1},
+ Stats{TeamNumber: 1235, MatchNumber: 94, ShotsMissed: 2, UpperGoalShots: 2, LowerGoalShots: 2, ShotsMissedAuto: 2, UpperGoalAuto: 2, LowerGoalAuto: 2, PlayedDefense: 2, Climbing: 2},
+ Stats{TeamNumber: 1234, MatchNumber: 94, ShotsMissed: 4, UpperGoalShots: 4, LowerGoalShots: 4, ShotsMissedAuto: 4, UpperGoalAuto: 4, LowerGoalAuto: 4, PlayedDefense: 7, Climbing: 2},
+ Stats{TeamNumber: 1233, MatchNumber: 94, ShotsMissed: 3, UpperGoalShots: 3, LowerGoalShots: 3, ShotsMissedAuto: 3, UpperGoalAuto: 3, LowerGoalAuto: 3, PlayedDefense: 3, Climbing: 3},
+ Stats{TeamNumber: 1232, MatchNumber: 94, ShotsMissed: 5, UpperGoalShots: 5, LowerGoalShots: 5, ShotsMissedAuto: 5, UpperGoalAuto: 5, LowerGoalAuto: 5, PlayedDefense: 7, Climbing: 1},
+ Stats{TeamNumber: 1231, MatchNumber: 94, ShotsMissed: 6, UpperGoalShots: 6, LowerGoalShots: 6, ShotsMissedAuto: 6, UpperGoalAuto: 6, LowerGoalAuto: 6, PlayedDefense: 7, Climbing: 1},
+ Stats{TeamNumber: 1239, MatchNumber: 94, ShotsMissed: 7, UpperGoalShots: 7, LowerGoalShots: 7, ShotsMissedAuto: 7, UpperGoalAuto: 7, LowerGoalAuto: 3, PlayedDefense: 7, Climbing: 1},
}
- db.AddToMatch(Match{matchNumber: 94, round: 1, compLevel: "quals", r1: 1235, r2: 1234, r3: 1233, b1: 1232, b2: 1231, b3: 1239})
+ db.AddToMatch(Match{MatchNumber: 94, Round: 1, CompLevel: "quals", R1: 1235, R2: 1234, R3: 1233, B1: 1232, B2: 1231, B3: 1239})
for i := 0; i < len(testDatabase); i++ {
db.AddToStats(testDatabase[i])
}
correct := []Stats{
- Stats{teamNumber: 1235, matchNumber: 94, shotsMissed: 2, upperGoalShots: 2, lowerGoalShots: 2, shotsMissedAuto: 2, upperGoalAuto: 2, lowerGoalAuto: 2, playedDefense: 2, climbing: 2},
+ Stats{TeamNumber: 1235, MatchNumber: 94, ShotsMissed: 2, UpperGoalShots: 2, LowerGoalShots: 2, ShotsMissedAuto: 2, UpperGoalAuto: 2, LowerGoalAuto: 2, PlayedDefense: 2, Climbing: 2},
}
got, error_ := db.QueryStats(1235)
if error_ != nil {
@@ -121,11 +121,11 @@
defer db.Delete()
correct := []Match{
- Match{matchNumber: 2, round: 1, compLevel: "quals", r1: 251, r2: 169, r3: 286, b1: 253, b2: 538, b3: 149, r1ID: 1, r2ID: 2, r3ID: 3, b1ID: 4, b2ID: 5, b3ID: 6},
- Match{matchNumber: 3, round: 1, compLevel: "quals", r1: 147, r2: 421, r3: 538, b1: 126, b2: 448, b3: 262, r1ID: 7, r2ID: 8, r3ID: 9, b1ID: 10, b2ID: 11, b3ID: 12},
- Match{matchNumber: 4, round: 1, compLevel: "quals", r1: 251, r2: 169, r3: 286, b1: 653, b2: 538, b3: 149, r1ID: 13, r2ID: 14, r3ID: 15, b1ID: 16, b2ID: 17, b3ID: 18},
- Match{matchNumber: 5, round: 1, compLevel: "quals", r1: 198, r2: 1421, r3: 538, b1: 26, b2: 448, b3: 262, r1ID: 19, r2ID: 20, r3ID: 21, b1ID: 22, b2ID: 23, b3ID: 24},
- Match{matchNumber: 6, round: 1, compLevel: "quals", r1: 251, r2: 188, r3: 286, b1: 555, b2: 538, b3: 149, r1ID: 25, r2ID: 26, r3ID: 27, b1ID: 28, b2ID: 29, b3ID: 30},
+ Match{MatchNumber: 2, Round: 1, CompLevel: "quals", R1: 251, R2: 169, R3: 286, B1: 253, B2: 538, B3: 149, r1ID: 1, r2ID: 2, r3ID: 3, b1ID: 4, b2ID: 5, b3ID: 6},
+ Match{MatchNumber: 3, Round: 1, CompLevel: "quals", R1: 147, R2: 421, R3: 538, B1: 126, B2: 448, B3: 262, r1ID: 7, r2ID: 8, r3ID: 9, b1ID: 10, b2ID: 11, b3ID: 12},
+ Match{MatchNumber: 4, Round: 1, CompLevel: "quals", R1: 251, R2: 169, R3: 286, B1: 653, B2: 538, B3: 149, r1ID: 13, r2ID: 14, r3ID: 15, b1ID: 16, b2ID: 17, b3ID: 18},
+ Match{MatchNumber: 5, Round: 1, CompLevel: "quals", R1: 198, R2: 1421, R3: 538, B1: 26, B2: 448, B3: 262, r1ID: 19, r2ID: 20, r3ID: 21, b1ID: 22, b2ID: 23, b3ID: 24},
+ Match{MatchNumber: 6, Round: 1, CompLevel: "quals", R1: 251, R2: 188, R3: 286, B1: 555, B2: 538, B3: 149, r1ID: 25, r2ID: 26, r3ID: 27, b1ID: 28, b2ID: 29, b3ID: 30},
}
for i := 0; i < len(correct); i++ {
db.AddToMatch(correct[i])
@@ -144,14 +144,14 @@
defer db.Delete()
correct := []Stats{
- Stats{teamNumber: 1235, matchNumber: 94, shotsMissed: 2, upperGoalShots: 2, lowerGoalShots: 2, shotsMissedAuto: 2, upperGoalAuto: 2, lowerGoalAuto: 2, playedDefense: 2, climbing: 2},
- Stats{teamNumber: 1236, matchNumber: 94, shotsMissed: 4, upperGoalShots: 4, lowerGoalShots: 4, shotsMissedAuto: 4, upperGoalAuto: 4, lowerGoalAuto: 4, playedDefense: 7, climbing: 2},
- Stats{teamNumber: 1237, matchNumber: 94, shotsMissed: 3, upperGoalShots: 3, lowerGoalShots: 3, shotsMissedAuto: 3, upperGoalAuto: 3, lowerGoalAuto: 3, playedDefense: 3, climbing: 3},
- Stats{teamNumber: 1238, matchNumber: 94, shotsMissed: 5, upperGoalShots: 5, lowerGoalShots: 5, shotsMissedAuto: 5, upperGoalAuto: 5, lowerGoalAuto: 5, playedDefense: 7, climbing: 1},
- Stats{teamNumber: 1239, matchNumber: 94, shotsMissed: 6, upperGoalShots: 6, lowerGoalShots: 6, shotsMissedAuto: 6, upperGoalAuto: 6, lowerGoalAuto: 6, playedDefense: 7, climbing: 1},
- Stats{teamNumber: 1233, matchNumber: 94, shotsMissed: 7, upperGoalShots: 7, lowerGoalShots: 7, shotsMissedAuto: 7, upperGoalAuto: 7, lowerGoalAuto: 3, playedDefense: 7, climbing: 1},
+ Stats{TeamNumber: 1235, MatchNumber: 94, ShotsMissed: 2, UpperGoalShots: 2, LowerGoalShots: 2, ShotsMissedAuto: 2, UpperGoalAuto: 2, LowerGoalAuto: 2, PlayedDefense: 2, Climbing: 2},
+ Stats{TeamNumber: 1236, MatchNumber: 94, ShotsMissed: 4, UpperGoalShots: 4, LowerGoalShots: 4, ShotsMissedAuto: 4, UpperGoalAuto: 4, LowerGoalAuto: 4, PlayedDefense: 7, Climbing: 2},
+ Stats{TeamNumber: 1237, MatchNumber: 94, ShotsMissed: 3, UpperGoalShots: 3, LowerGoalShots: 3, ShotsMissedAuto: 3, UpperGoalAuto: 3, LowerGoalAuto: 3, PlayedDefense: 3, Climbing: 3},
+ Stats{TeamNumber: 1238, MatchNumber: 94, ShotsMissed: 5, UpperGoalShots: 5, LowerGoalShots: 5, ShotsMissedAuto: 5, UpperGoalAuto: 5, LowerGoalAuto: 5, PlayedDefense: 7, Climbing: 1},
+ Stats{TeamNumber: 1239, MatchNumber: 94, ShotsMissed: 6, UpperGoalShots: 6, LowerGoalShots: 6, ShotsMissedAuto: 6, UpperGoalAuto: 6, LowerGoalAuto: 6, PlayedDefense: 7, Climbing: 1},
+ Stats{TeamNumber: 1233, MatchNumber: 94, ShotsMissed: 7, UpperGoalShots: 7, LowerGoalShots: 7, ShotsMissedAuto: 7, UpperGoalAuto: 7, LowerGoalAuto: 3, PlayedDefense: 7, Climbing: 1},
}
- db.AddToMatch(Match{matchNumber: 94, round: 1, compLevel: "quals", r1: 1235, r2: 1236, r3: 1237, b1: 1238, b2: 1239, b3: 1233})
+ db.AddToMatch(Match{MatchNumber: 94, Round: 1, CompLevel: "quals", R1: 1235, R2: 1236, R3: 1237, B1: 1238, B2: 1239, B3: 1233})
for i := 0; i < len(correct); i++ {
db.AddToStats(correct[i])
}
diff --git a/scouting/scouting_test.protractor.on-prepare.js b/scouting/scouting_test.protractor.on-prepare.js
new file mode 100644
index 0000000..7919fe7
--- /dev/null
+++ b/scouting/scouting_test.protractor.on-prepare.js
@@ -0,0 +1,22 @@
+// The function exported from this file is used by the protractor_web_test_suite.
+// It is passed to the `onPrepare` configuration setting in protractor and executed
+// before running tests.
+//
+// If the function returns a promise, as it does here, protractor will wait
+// for the promise to resolve before running tests.
+
+const protractorUtils = require('@bazel/protractor/protractor-utils');
+const protractor = require('protractor');
+
+module.exports = function(config) {
+ // In this example, `@bazel/protractor/protractor-utils` is used to run
+ // the server. protractorUtils.runServer() runs the server on a randomly
+ // selected port (given a port flag to pass to the server as an argument).
+ // The port used is returned in serverSpec and the protractor serverUrl
+ // is the configured.
+ return protractorUtils
+ .runServer(config.workspace, config.server, '--port', [])
+ .then(serverSpec => {
+ protractor.browser.baseUrl = `http://localhost:${serverSpec.port}`;
+ });
+};
diff --git a/scouting/scouting_test.py b/scouting/scouting_test.py
deleted file mode 100644
index 3b62224..0000000
--- a/scouting/scouting_test.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# TODO(phil): Delete this and replace it with a selenium test. Preferably
-# written in either Javascript or Go.
-
-import socket
-import subprocess
-import time
-import unittest
-import urllib.request
-
-class TestDebugCli(unittest.TestCase):
-
- def setUp(self):
- self.webserver = subprocess.Popen(["scouting/scouting"])
-
- # Wait for the server to respond to requests.
- while True:
- try:
- connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- connection.connect(("localhost", 8080))
- connection.close()
- break
- except ConnectionRefusedError:
- connection.close()
- time.sleep(0.01)
-
- def tearDown(self):
- self.webserver.terminate()
- self.webserver.wait()
-
- def test_index_html(self):
- """Makes sure that we the scouting server is serving our main index.html file."""
- with urllib.request.urlopen("http://localhost:8080/") as file:
- html = file.read().decode("utf-8")
- self.assertIn("<my-app></my-app>", html)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/scouting/scouting_test.ts b/scouting/scouting_test.ts
new file mode 100644
index 0000000..68dba52
--- /dev/null
+++ b/scouting/scouting_test.ts
@@ -0,0 +1,32 @@
+import {browser, by, element} from 'protractor';
+
+class AppPage {
+ async navigateTo() {
+ await browser.get(browser.baseUrl);
+ }
+
+ // Wait for basically forever for these elements to appear.
+ // Bazel will manage the timeouts.
+ async waitForElement(el, timeout = 1000000) {
+ await browser.wait(() => el.isPresent(), timeout);
+ await browser.wait(() => el.isDisplayed(), timeout);
+ return el;
+ }
+
+ async getParagraphText() {
+ return (await this.waitForElement(element(by.css('.header')))).getText();
+ }
+}
+
+describe('The scouting web page', () => {
+ let page: AppPage;
+
+ beforeEach(() => {
+ page = new AppPage();
+ });
+
+ it('should display: This is an app.', async () => {
+ await page.navigateTo();
+ expect(await page.getParagraphText()).toEqual('Team Selection');
+ });
+});
diff --git a/scouting/scraping/BUILD b/scouting/scraping/BUILD
index d9248f8..8681ddd 100644
--- a/scouting/scraping/BUILD
+++ b/scouting/scraping/BUILD
@@ -1,5 +1,14 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
+filegroup(
+ name = "test_data",
+ srcs = [
+ # Generated with: bazel run //scouting/scraping:scraping_demo -- --json
+ "test_data/2016_nytr.json",
+ ],
+ visibility = ["//visibility:public"],
+)
+
go_library(
name = "scraping",
srcs = [
diff --git a/scouting/scraping/scrape.go b/scouting/scraping/scrape.go
index fa20f7b..170fe50 100644
--- a/scouting/scraping/scrape.go
+++ b/scouting/scraping/scrape.go
@@ -4,15 +4,17 @@
import (
"encoding/json"
"errors"
+ "fmt"
"io/ioutil"
- "log"
"net/http"
"os"
+ "strconv"
)
// Stores the TBA API key to access the API.
-type params struct {
- ApiKey string `json:"api_key"`
+type scrapingConfig struct {
+ ApiKey string `json:"api_key"`
+ BaseUrl string `json:"base_url"`
}
// Takes in year and FIRST event code and returns all matches in that event according to TBA.
@@ -22,64 +24,64 @@
//{
// api_key:"myTBAapiKey"
//}
-func AllMatches(year, eventCode, filePath string) ([]Match, error) {
- if filePath == "" {
- filePath = os.Getenv("BUILD_WORKSPACE_DIRECTORY") + "/scouting_config.json"
+func AllMatches(year int32, eventCode, configPath string) ([]Match, error) {
+ if configPath == "" {
+ configPath = os.Getenv("BUILD_WORKSPACE_DIRECTORY") + "/scouting_config.json"
}
+
// Takes the filepath and grabs the api key from the json.
- content, err := ioutil.ReadFile(filePath)
+ content, err := ioutil.ReadFile(configPath)
if err != nil {
- log.Fatal(err)
+ return nil, errors.New(fmt.Sprint("Failed to open config at ", configPath, ": ", 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)
+ var config scrapingConfig
+ if err := json.Unmarshal([]byte(content), &config); err != nil {
+ return nil, errors.New(fmt.Sprint("Failed to parse config file as JSON: ", err))
+ }
+
+ // Perform some basic validation on the data.
+ if config.ApiKey == "" {
+ return nil, errors.New("Missing 'api_key' in config JSON.")
+ }
+ if config.BaseUrl == "" {
+ config.BaseUrl = "https://www.thebluealliance.com"
}
// Create the TBA event key for the year and event code.
- eventKey := year + eventCode
-
- // Create the client for HTTP requests.
- client := &http.Client{}
+ eventKey := strconv.Itoa(int(year)) + eventCode
// Create a get request for the match info.
- req, err := http.NewRequest("GET", "https://www.thebluealliance.com/api/v3/event/"+eventKey+"/matches", nil)
-
+ req, err := http.NewRequest("GET", config.BaseUrl+"/api/v3/event/"+eventKey+"/matches", nil)
if err != nil {
- return nil, errors.New("failed to build http request")
+ return nil, errors.New(fmt.Sprint("Failed to build http request: ", err))
}
// Add the auth key header to the request.
- req.Header.Add("X-TBA-Auth-Key", passed_params.ApiKey)
+ req.Header.Add("X-TBA-Auth-Key", config.ApiKey)
- // Make the API request
+ // Make the API request.
+ client := &http.Client{}
resp, err := client.Do(req)
-
if err != nil {
- return nil, err
+ return nil, errors.New(fmt.Sprint("Failed to make TBA API request: ", 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()
+ if resp.StatusCode != 200 {
+ return nil, errors.New(fmt.Sprint("Got unexpected status code from TBA API request: ", resp.Status))
+ }
// 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())
+ return nil, errors.New(fmt.Sprint("Failed to read TBA API response: ", err))
}
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")
+ if err := json.Unmarshal([]byte(bodyBytes), &matches); err != nil {
+ return nil, errors.New(fmt.Sprint("Failed to parse JSON received from TBA: ", err))
}
return matches, nil
diff --git a/scouting/scraping/scraping_demo.go b/scouting/scraping/scraping_demo.go
index 1d727f3..0ea3e53 100644
--- a/scouting/scraping/scraping_demo.go
+++ b/scouting/scraping/scraping_demo.go
@@ -2,6 +2,9 @@
// To run the demo, ensure that you have a file named scouting_config.json at the workspace root with your TBA api key in it.
import (
+ "encoding/json"
+ "flag"
+ "fmt"
"log"
"github.com/davecgh/go-spew/spew"
@@ -9,12 +12,23 @@
)
func main() {
+ jsonPtr := flag.Bool("json", false, "If set, dump as JSON, rather than Go debug output.")
+ flag.Parse()
+
// Get all the matches.
- matches, err := scraping.AllMatches("2016", "nytr", "")
- // Fail on error.
+ matches, err := scraping.AllMatches(2016, "nytr", "")
if err != nil {
- log.Fatal("Error:", err.Error)
+ log.Fatal("Failed to scrape match list: ", err)
}
+
// Dump the matches.
- spew.Dump(matches)
+ if *jsonPtr {
+ jsonData, err := json.MarshalIndent(matches, "", " ")
+ if err != nil {
+ log.Fatal("Failed to turn match list into JSON: ", err)
+ }
+ fmt.Println(string(jsonData))
+ } else {
+ spew.Dump(matches)
+ }
}
diff --git a/scouting/scraping/test_data/2016_nytr.json b/scouting/scraping/test_data/2016_nytr.json
new file mode 100644
index 0000000..120d6d3
--- /dev/null
+++ b/scouting/scraping/test_data/2016_nytr.json
@@ -0,0 +1,10812 @@
+[
+ {
+ "Key": "2016nytr_f1m1",
+ "comp_level": "f",
+ "set_number": 1,
+ "match_number": 1,
+ "alliances": {
+ "red": {
+ "score": 168,
+ "team_keys": [
+ "frc3990",
+ "frc359",
+ "frc4508"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 115,
+ "team_keys": [
+ "frc20",
+ "frc5254",
+ "frc1665"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458418140,
+ "predicted_time": 0,
+ "actual_time": 1458417643,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_f1m2",
+ "comp_level": "f",
+ "set_number": 1,
+ "match_number": 2,
+ "alliances": {
+ "red": {
+ "score": 134,
+ "team_keys": [
+ "frc3990",
+ "frc359",
+ "frc4508"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 136,
+ "team_keys": [
+ "frc20",
+ "frc5254",
+ "frc1665"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458418920,
+ "predicted_time": 0,
+ "actual_time": 1458418685,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_f1m3",
+ "comp_level": "f",
+ "set_number": 1,
+ "match_number": 3,
+ "alliances": {
+ "red": {
+ "score": 164,
+ "team_keys": [
+ "frc3990",
+ "frc359",
+ "frc4508"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 147,
+ "team_keys": [
+ "frc20",
+ "frc5254",
+ "frc1665"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458419700,
+ "predicted_time": 0,
+ "actual_time": 1458419924,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qf1m1",
+ "comp_level": "qf",
+ "set_number": 1,
+ "match_number": 1,
+ "alliances": {
+ "red": {
+ "score": 121,
+ "team_keys": [
+ "frc3990",
+ "frc359",
+ "frc4508"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 107,
+ "team_keys": [
+ "frc3044",
+ "frc4930",
+ "frc4481"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458408600,
+ "predicted_time": 0,
+ "actual_time": 1458408170,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qf1m2",
+ "comp_level": "qf",
+ "set_number": 1,
+ "match_number": 2,
+ "alliances": {
+ "red": {
+ "score": 170,
+ "team_keys": [
+ "frc3990",
+ "frc359",
+ "frc4508"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 80,
+ "team_keys": [
+ "frc3044",
+ "frc4930",
+ "frc4481"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458410460,
+ "predicted_time": 0,
+ "actual_time": 1458410300,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qf2m1",
+ "comp_level": "qf",
+ "set_number": 2,
+ "match_number": 1,
+ "alliances": {
+ "red": {
+ "score": 107,
+ "team_keys": [
+ "frc5240",
+ "frc3419",
+ "frc663"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 110,
+ "team_keys": [
+ "frc1493",
+ "frc48",
+ "frc1551"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458409020,
+ "predicted_time": 0,
+ "actual_time": 1458408692,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qf2m2",
+ "comp_level": "qf",
+ "set_number": 2,
+ "match_number": 2,
+ "alliances": {
+ "red": {
+ "score": 116,
+ "team_keys": [
+ "frc5240",
+ "frc3419",
+ "frc663"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 78,
+ "team_keys": [
+ "frc1493",
+ "frc48",
+ "frc1551"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458410880,
+ "predicted_time": 0,
+ "actual_time": 1458410748,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qf2m3",
+ "comp_level": "qf",
+ "set_number": 2,
+ "match_number": 3,
+ "alliances": {
+ "red": {
+ "score": 104,
+ "team_keys": [
+ "frc5240",
+ "frc3419",
+ "frc663"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 94,
+ "team_keys": [
+ "frc1493",
+ "frc48",
+ "frc1551"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458412920,
+ "predicted_time": 0,
+ "actual_time": 1458412900,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qf3m1",
+ "comp_level": "qf",
+ "set_number": 3,
+ "match_number": 1,
+ "alliances": {
+ "red": {
+ "score": 132,
+ "team_keys": [
+ "frc20",
+ "frc5254",
+ "frc229"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 84,
+ "team_keys": [
+ "frc3003",
+ "frc358",
+ "frc527"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458409440,
+ "predicted_time": 0,
+ "actual_time": 1458409186,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qf3m2",
+ "comp_level": "qf",
+ "set_number": 3,
+ "match_number": 2,
+ "alliances": {
+ "red": {
+ "score": 144,
+ "team_keys": [
+ "frc20",
+ "frc5254",
+ "frc229"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 103,
+ "team_keys": [
+ "frc3003",
+ "frc358",
+ "frc527"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458411300,
+ "predicted_time": 0,
+ "actual_time": 1458411317,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qf4m1",
+ "comp_level": "qf",
+ "set_number": 4,
+ "match_number": 1,
+ "alliances": {
+ "red": {
+ "score": 147,
+ "team_keys": [
+ "frc2791",
+ "frc5236",
+ "frc3624"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 121,
+ "team_keys": [
+ "frc333",
+ "frc250",
+ "frc145"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458409860,
+ "predicted_time": 0,
+ "actual_time": 1458409739,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qf4m2",
+ "comp_level": "qf",
+ "set_number": 4,
+ "match_number": 2,
+ "alliances": {
+ "red": {
+ "score": 106,
+ "team_keys": [
+ "frc2791",
+ "frc5236",
+ "frc3624"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 151,
+ "team_keys": [
+ "frc333",
+ "frc250",
+ "frc145"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458411720,
+ "predicted_time": 0,
+ "actual_time": 1458411761,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qf4m3",
+ "comp_level": "qf",
+ "set_number": 4,
+ "match_number": 3,
+ "alliances": {
+ "red": {
+ "score": 165,
+ "team_keys": [
+ "frc2791",
+ "frc5236",
+ "frc3624"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 89,
+ "team_keys": [
+ "frc333",
+ "frc250",
+ "frc145"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458413760,
+ "predicted_time": 0,
+ "actual_time": 1458413371,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm1",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 1,
+ "alliances": {
+ "red": {
+ "score": 62,
+ "team_keys": [
+ "frc5240",
+ "frc3003",
+ "frc3419"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 85,
+ "team_keys": [
+ "frc3990",
+ "frc371",
+ "frc2791"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458306000,
+ "predicted_time": 0,
+ "actual_time": 1458306152,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm10",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 10,
+ "alliances": {
+ "red": {
+ "score": 79,
+ "team_keys": [
+ "frc250",
+ "frc5879",
+ "frc2791"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 85,
+ "team_keys": [
+ "frc371",
+ "frc4856",
+ "frc359"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458310680,
+ "predicted_time": 0,
+ "actual_time": 1458310963,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm11",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 11,
+ "alliances": {
+ "red": {
+ "score": 40,
+ "team_keys": [
+ "frc1551",
+ "frc1665",
+ "frc3624"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": [
+ "frc3624"
+ ]
+ },
+ "blue": {
+ "score": 82,
+ "team_keys": [
+ "frc20",
+ "frc3044",
+ "frc4093"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458311160,
+ "predicted_time": 0,
+ "actual_time": 1458311501,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm12",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 12,
+ "alliances": {
+ "red": {
+ "score": 76,
+ "team_keys": [
+ "frc3990",
+ "frc4481",
+ "frc5881"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 45,
+ "team_keys": [
+ "frc4203",
+ "frc663",
+ "frc527"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458311640,
+ "predicted_time": 0,
+ "actual_time": 1458311984,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm13",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 13,
+ "alliances": {
+ "red": {
+ "score": 24,
+ "team_keys": [
+ "frc1450",
+ "frc4856",
+ "frc5879"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": [
+ "frc5879"
+ ]
+ },
+ "blue": {
+ "score": 60,
+ "team_keys": [
+ "frc5254",
+ "frc5585",
+ "frc371"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458312120,
+ "predicted_time": 0,
+ "actual_time": 1458312573,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm14",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 14,
+ "alliances": {
+ "red": {
+ "score": 34,
+ "team_keys": [
+ "frc4508",
+ "frc5149",
+ "frc250"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 44,
+ "team_keys": [
+ "frc5964",
+ "frc5240",
+ "frc1665"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458312600,
+ "predicted_time": 0,
+ "actual_time": 1458313136,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm15",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 15,
+ "alliances": {
+ "red": {
+ "score": 91,
+ "team_keys": [
+ "frc2791",
+ "frc5881",
+ "frc527"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 85,
+ "team_keys": [
+ "frc48",
+ "frc3624",
+ "frc333"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": [
+ "frc3624"
+ ]
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458313080,
+ "predicted_time": 0,
+ "actual_time": 1458313525,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm16",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 16,
+ "alliances": {
+ "red": {
+ "score": 95,
+ "team_keys": [
+ "frc229",
+ "frc1493",
+ "frc359"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 77,
+ "team_keys": [
+ "frc3419",
+ "frc3044",
+ "frc663"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458313740,
+ "predicted_time": 0,
+ "actual_time": 1458314003,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm17",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 17,
+ "alliances": {
+ "red": {
+ "score": 45,
+ "team_keys": [
+ "frc3990",
+ "frc4203",
+ "frc5943"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 86,
+ "team_keys": [
+ "frc1551",
+ "frc358",
+ "frc145"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458314220,
+ "predicted_time": 0,
+ "actual_time": 1458314433,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm18",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 18,
+ "alliances": {
+ "red": {
+ "score": 75,
+ "team_keys": [
+ "frc4481",
+ "frc4930",
+ "frc4093"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 88,
+ "team_keys": [
+ "frc5236",
+ "frc3003",
+ "frc20"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458314700,
+ "predicted_time": 0,
+ "actual_time": 1458314859,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm19",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 19,
+ "alliances": {
+ "red": {
+ "score": 88,
+ "team_keys": [
+ "frc48",
+ "frc5149",
+ "frc5254"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 62,
+ "team_keys": [
+ "frc229",
+ "frc663",
+ "frc4856"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458315180,
+ "predicted_time": 0,
+ "actual_time": 1458315401,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm2",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 2,
+ "alliances": {
+ "red": {
+ "score": 85,
+ "team_keys": [
+ "frc48",
+ "frc3044",
+ "frc4856"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": [
+ "frc4856"
+ ]
+ },
+ "blue": {
+ "score": 15,
+ "team_keys": [
+ "frc4481",
+ "frc358",
+ "frc3624"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": [
+ "frc3624"
+ ]
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458306480,
+ "predicted_time": 0,
+ "actual_time": 1458306689,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm20",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 20,
+ "alliances": {
+ "red": {
+ "score": 10,
+ "team_keys": [
+ "frc1665",
+ "frc371",
+ "frc5943"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 65,
+ "team_keys": [
+ "frc5585",
+ "frc3624",
+ "frc3044"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458315660,
+ "predicted_time": 0,
+ "actual_time": 1458315911,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm21",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 21,
+ "alliances": {
+ "red": {
+ "score": 30,
+ "team_keys": [
+ "frc1551",
+ "frc4203",
+ "frc250"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 81,
+ "team_keys": [
+ "frc333",
+ "frc20",
+ "frc1493"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458316140,
+ "predicted_time": 0,
+ "actual_time": 1458316579,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm22",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 22,
+ "alliances": {
+ "red": {
+ "score": 124,
+ "team_keys": [
+ "frc359",
+ "frc3419",
+ "frc145"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 66,
+ "team_keys": [
+ "frc2791",
+ "frc4481",
+ "frc3003"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458316800,
+ "predicted_time": 0,
+ "actual_time": 1458316995,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm23",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 23,
+ "alliances": {
+ "red": {
+ "score": 63,
+ "team_keys": [
+ "frc5964",
+ "frc4508",
+ "frc5881"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 81,
+ "team_keys": [
+ "frc4093",
+ "frc1450",
+ "frc3990"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458317280,
+ "predicted_time": 0,
+ "actual_time": 1458317393,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm24",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 24,
+ "alliances": {
+ "red": {
+ "score": 26,
+ "team_keys": [
+ "frc358",
+ "frc5236",
+ "frc527"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 47,
+ "team_keys": [
+ "frc5240",
+ "frc4930",
+ "frc5879"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458321360,
+ "predicted_time": 0,
+ "actual_time": 1458321119,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm25",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 25,
+ "alliances": {
+ "red": {
+ "score": 69,
+ "team_keys": [
+ "frc250",
+ "frc371",
+ "frc3003"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 62,
+ "team_keys": [
+ "frc5585",
+ "frc4481",
+ "frc4203"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458321840,
+ "predicted_time": 0,
+ "actual_time": 1458321835,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm26",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 26,
+ "alliances": {
+ "red": {
+ "score": 99,
+ "team_keys": [
+ "frc229",
+ "frc333",
+ "frc5881"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 115,
+ "team_keys": [
+ "frc1665",
+ "frc359",
+ "frc3990"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458322320,
+ "predicted_time": 0,
+ "actual_time": 1458322308,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm27",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 27,
+ "alliances": {
+ "red": {
+ "score": 73,
+ "team_keys": [
+ "frc5240",
+ "frc527",
+ "frc20"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 47,
+ "team_keys": [
+ "frc4856",
+ "frc4930",
+ "frc5943"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458322800,
+ "predicted_time": 0,
+ "actual_time": 1458322685,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm28",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 28,
+ "alliances": {
+ "red": {
+ "score": 29,
+ "team_keys": [
+ "frc5149",
+ "frc3624",
+ "frc145"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 84,
+ "team_keys": [
+ "frc5254",
+ "frc358",
+ "frc1450"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458323460,
+ "predicted_time": 0,
+ "actual_time": 1458323094,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm29",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 29,
+ "alliances": {
+ "red": {
+ "score": 51,
+ "team_keys": [
+ "frc1493",
+ "frc4093",
+ "frc5879"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 82,
+ "team_keys": [
+ "frc5964",
+ "frc48",
+ "frc3419"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458323940,
+ "predicted_time": 0,
+ "actual_time": 1458324109,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm3",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 3,
+ "alliances": {
+ "red": {
+ "score": 60,
+ "team_keys": [
+ "frc663",
+ "frc4093",
+ "frc333"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 64,
+ "team_keys": [
+ "frc5585",
+ "frc145",
+ "frc1450"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458306960,
+ "predicted_time": 0,
+ "actual_time": 1458307302,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm30",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 30,
+ "alliances": {
+ "red": {
+ "score": 54,
+ "team_keys": [
+ "frc3044",
+ "frc1551",
+ "frc4508"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 93,
+ "team_keys": [
+ "frc5236",
+ "frc663",
+ "frc2791"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458324420,
+ "predicted_time": 0,
+ "actual_time": 1458324499,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm31",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 31,
+ "alliances": {
+ "red": {
+ "score": 66,
+ "team_keys": [
+ "frc5585",
+ "frc20",
+ "frc4856"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 112,
+ "team_keys": [
+ "frc333",
+ "frc4930",
+ "frc3990"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458324900,
+ "predicted_time": 0,
+ "actual_time": 1458325029,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm32",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 32,
+ "alliances": {
+ "red": {
+ "score": 49,
+ "team_keys": [
+ "frc145",
+ "frc371",
+ "frc4093"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 92,
+ "team_keys": [
+ "frc5879",
+ "frc5964",
+ "frc359"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458325380,
+ "predicted_time": 0,
+ "actual_time": 1458325592,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm33",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 33,
+ "alliances": {
+ "red": {
+ "score": 74,
+ "team_keys": [
+ "frc3624",
+ "frc527",
+ "frc229"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 67,
+ "team_keys": [
+ "frc5236",
+ "frc4203",
+ "frc4508"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458325860,
+ "predicted_time": 0,
+ "actual_time": 1458325971,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm34",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 34,
+ "alliances": {
+ "red": {
+ "score": 70,
+ "team_keys": [
+ "frc4481",
+ "frc5149",
+ "frc1450"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 86,
+ "team_keys": [
+ "frc1551",
+ "frc2791",
+ "frc1493"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458326520,
+ "predicted_time": 0,
+ "actual_time": 1458326383,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm35",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 35,
+ "alliances": {
+ "red": {
+ "score": 72,
+ "team_keys": [
+ "frc663",
+ "frc48",
+ "frc5943"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 83,
+ "team_keys": [
+ "frc1665",
+ "frc5254",
+ "frc3003"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458327000,
+ "predicted_time": 0,
+ "actual_time": 1458326796,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm36",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 36,
+ "alliances": {
+ "red": {
+ "score": 107,
+ "team_keys": [
+ "frc3044",
+ "frc5240",
+ "frc250"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 74,
+ "team_keys": [
+ "frc3419",
+ "frc358",
+ "frc5881"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458327480,
+ "predicted_time": 0,
+ "actual_time": 1458327181,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm37",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 37,
+ "alliances": {
+ "red": {
+ "score": 66,
+ "team_keys": [
+ "frc4481",
+ "frc145",
+ "frc1493"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 90,
+ "team_keys": [
+ "frc527",
+ "frc371",
+ "frc333"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458327960,
+ "predicted_time": 0,
+ "actual_time": 1458327852,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm38",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 38,
+ "alliances": {
+ "red": {
+ "score": 44,
+ "team_keys": [
+ "frc5236",
+ "frc4856",
+ "frc5149"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 111,
+ "team_keys": [
+ "frc20",
+ "frc48",
+ "frc3990"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458328440,
+ "predicted_time": 0,
+ "actual_time": 1458328284,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm39",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 39,
+ "alliances": {
+ "red": {
+ "score": 99,
+ "team_keys": [
+ "frc3419",
+ "frc2791",
+ "frc4930"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 67,
+ "team_keys": [
+ "frc5964",
+ "frc1551",
+ "frc663"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458328920,
+ "predicted_time": 0,
+ "actual_time": 1458328709,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm4",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 4,
+ "alliances": {
+ "red": {
+ "score": 73,
+ "team_keys": [
+ "frc4508",
+ "frc4930",
+ "frc1493"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 78,
+ "team_keys": [
+ "frc5254",
+ "frc250",
+ "frc5943"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458307620,
+ "predicted_time": 0,
+ "actual_time": 1458307725,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm40",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 40,
+ "alliances": {
+ "red": {
+ "score": 82,
+ "team_keys": [
+ "frc5254",
+ "frc5879",
+ "frc4203"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 77,
+ "team_keys": [
+ "frc5881",
+ "frc5943",
+ "frc3044"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458329580,
+ "predicted_time": 0,
+ "actual_time": 1458329683,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm41",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 41,
+ "alliances": {
+ "red": {
+ "score": 70,
+ "team_keys": [
+ "frc3624",
+ "frc1450",
+ "frc5240"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 77,
+ "team_keys": [
+ "frc4093",
+ "frc250",
+ "frc229"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458330060,
+ "predicted_time": 0,
+ "actual_time": 1458330063,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm42",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 42,
+ "alliances": {
+ "red": {
+ "score": 109,
+ "team_keys": [
+ "frc3003",
+ "frc359",
+ "frc358"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 39,
+ "team_keys": [
+ "frc5585",
+ "frc1665",
+ "frc4508"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458330540,
+ "predicted_time": 0,
+ "actual_time": 1458330433,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm43",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 43,
+ "alliances": {
+ "red": {
+ "score": 61,
+ "team_keys": [
+ "frc5881",
+ "frc4203",
+ "frc145"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 64,
+ "team_keys": [
+ "frc3044",
+ "frc4930",
+ "frc527"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458331020,
+ "predicted_time": 0,
+ "actual_time": 1458330818,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm44",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 44,
+ "alliances": {
+ "red": {
+ "score": 101,
+ "team_keys": [
+ "frc5254",
+ "frc333",
+ "frc4481"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 77,
+ "team_keys": [
+ "frc5149",
+ "frc5240",
+ "frc2791"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458331500,
+ "predicted_time": 0,
+ "actual_time": 1458331224,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm45",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 45,
+ "alliances": {
+ "red": {
+ "score": 60,
+ "team_keys": [
+ "frc5964",
+ "frc4093",
+ "frc3003"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 62,
+ "team_keys": [
+ "frc250",
+ "frc4856",
+ "frc1493"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458331980,
+ "predicted_time": 0,
+ "actual_time": 1458331735,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm46",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 46,
+ "alliances": {
+ "red": {
+ "score": 56,
+ "team_keys": [
+ "frc371",
+ "frc20",
+ "frc3624"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 107,
+ "team_keys": [
+ "frc663",
+ "frc4508",
+ "frc359"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458332640,
+ "predicted_time": 0,
+ "actual_time": 1458332313,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm47",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 47,
+ "alliances": {
+ "red": {
+ "score": 72,
+ "team_keys": [
+ "frc1450",
+ "frc1665",
+ "frc48"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 86,
+ "team_keys": [
+ "frc358",
+ "frc5879",
+ "frc3990"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458333120,
+ "predicted_time": 0,
+ "actual_time": 1458333025,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm48",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 48,
+ "alliances": {
+ "red": {
+ "score": 49,
+ "team_keys": [
+ "frc5943",
+ "frc5585",
+ "frc229"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 102,
+ "team_keys": [
+ "frc1551",
+ "frc3419",
+ "frc5236"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458333600,
+ "predicted_time": 0,
+ "actual_time": 1458333472,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm49",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 49,
+ "alliances": {
+ "red": {
+ "score": 143,
+ "team_keys": [
+ "frc359",
+ "frc3624",
+ "frc5254"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 86,
+ "team_keys": [
+ "frc5964",
+ "frc4481",
+ "frc20"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458334080,
+ "predicted_time": 0,
+ "actual_time": 1458333898,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm5",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 5,
+ "alliances": {
+ "red": {
+ "score": 102,
+ "team_keys": [
+ "frc5236",
+ "frc359",
+ "frc5881"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 19,
+ "team_keys": [
+ "frc5149",
+ "frc4203",
+ "frc5964"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458308100,
+ "predicted_time": 0,
+ "actual_time": 1458308171,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm50",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 50,
+ "alliances": {
+ "red": {
+ "score": 82,
+ "team_keys": [
+ "frc5240",
+ "frc1493",
+ "frc663"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 54,
+ "team_keys": [
+ "frc5879",
+ "frc3003",
+ "frc145"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458334560,
+ "predicted_time": 0,
+ "actual_time": 1458334725,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm51",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 51,
+ "alliances": {
+ "red": {
+ "score": 69,
+ "team_keys": [
+ "frc2791",
+ "frc5943",
+ "frc358"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 52,
+ "team_keys": [
+ "frc5585",
+ "frc5881",
+ "frc4093"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458335040,
+ "predicted_time": 0,
+ "actual_time": 1458335144,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm52",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 52,
+ "alliances": {
+ "red": {
+ "score": 101,
+ "team_keys": [
+ "frc5236",
+ "frc3990",
+ "frc229"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 82,
+ "team_keys": [
+ "frc333",
+ "frc1450",
+ "frc250"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458335700,
+ "predicted_time": 0,
+ "actual_time": 1458335606,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm53",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 53,
+ "alliances": {
+ "red": {
+ "score": 55,
+ "team_keys": [
+ "frc371",
+ "frc3044",
+ "frc5149"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 102,
+ "team_keys": [
+ "frc48",
+ "frc4930",
+ "frc1551"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458336180,
+ "predicted_time": 0,
+ "actual_time": 1458336076,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm54",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 54,
+ "alliances": {
+ "red": {
+ "score": 89,
+ "team_keys": [
+ "frc1665",
+ "frc3419",
+ "frc4203"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 83,
+ "team_keys": [
+ "frc4508",
+ "frc527",
+ "frc4856"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458392400,
+ "predicted_time": 0,
+ "actual_time": 1458391888,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm55",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 55,
+ "alliances": {
+ "red": {
+ "score": 108,
+ "team_keys": [
+ "frc3990",
+ "frc3003",
+ "frc663"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 83,
+ "team_keys": [
+ "frc1493",
+ "frc3624",
+ "frc5943"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458392880,
+ "predicted_time": 0,
+ "actual_time": 1458392321,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm56",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 56,
+ "alliances": {
+ "red": {
+ "score": 94,
+ "team_keys": [
+ "frc5240",
+ "frc5585",
+ "frc333"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 68,
+ "team_keys": [
+ "frc5881",
+ "frc5879",
+ "frc48"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458393360,
+ "predicted_time": 0,
+ "actual_time": 1458393079,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm57",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 57,
+ "alliances": {
+ "red": {
+ "score": 86,
+ "team_keys": [
+ "frc3419",
+ "frc20",
+ "frc5149"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 71,
+ "team_keys": [
+ "frc358",
+ "frc3044",
+ "frc4203"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458393840,
+ "predicted_time": 0,
+ "actual_time": 1458393573,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm58",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 58,
+ "alliances": {
+ "red": {
+ "score": 97,
+ "team_keys": [
+ "frc5254",
+ "frc1551",
+ "frc4093"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 110,
+ "team_keys": [
+ "frc527",
+ "frc359",
+ "frc250"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458394500,
+ "predicted_time": 0,
+ "actual_time": 1458394319,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm59",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 59,
+ "alliances": {
+ "red": {
+ "score": 89,
+ "team_keys": [
+ "frc5964",
+ "frc4856",
+ "frc2791"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 101,
+ "team_keys": [
+ "frc1665",
+ "frc145",
+ "frc5236"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458394980,
+ "predicted_time": 0,
+ "actual_time": 1458394775,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm6",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 6,
+ "alliances": {
+ "red": {
+ "score": 50,
+ "team_keys": [
+ "frc5879",
+ "frc1665",
+ "frc527"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 86,
+ "team_keys": [
+ "frc229",
+ "frc20",
+ "frc1551"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458308580,
+ "predicted_time": 0,
+ "actual_time": 1458309050,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm60",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 60,
+ "alliances": {
+ "red": {
+ "score": 62,
+ "team_keys": [
+ "frc4481",
+ "frc4508",
+ "frc371"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 46,
+ "team_keys": [
+ "frc229",
+ "frc4930",
+ "frc1450"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458395460,
+ "predicted_time": 0,
+ "actual_time": 1458395186,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm61",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 61,
+ "alliances": {
+ "red": {
+ "score": 105,
+ "team_keys": [
+ "frc4093",
+ "frc48",
+ "frc527"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 70,
+ "team_keys": [
+ "frc359",
+ "frc5943",
+ "frc5149"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458395940,
+ "predicted_time": 0,
+ "actual_time": 1458395574,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm62",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 62,
+ "alliances": {
+ "red": {
+ "score": 61,
+ "team_keys": [
+ "frc663",
+ "frc358",
+ "frc20"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 84,
+ "team_keys": [
+ "frc5964",
+ "frc145",
+ "frc5254"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458396420,
+ "predicted_time": 0,
+ "actual_time": 1458395960,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm63",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 63,
+ "alliances": {
+ "red": {
+ "score": 57,
+ "team_keys": [
+ "frc1551",
+ "frc333",
+ "frc5879"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 80,
+ "team_keys": [
+ "frc4508",
+ "frc3624",
+ "frc3003"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458396900,
+ "predicted_time": 0,
+ "actual_time": 1458396366,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm64",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 64,
+ "alliances": {
+ "red": {
+ "score": 85,
+ "team_keys": [
+ "frc1665",
+ "frc3044",
+ "frc1493"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 101,
+ "team_keys": [
+ "frc5236",
+ "frc4481",
+ "frc5240"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458397560,
+ "predicted_time": 0,
+ "actual_time": 1458396974,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm65",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 65,
+ "alliances": {
+ "red": {
+ "score": 110,
+ "team_keys": [
+ "frc3990",
+ "frc4856",
+ "frc3419"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 50,
+ "team_keys": [
+ "frc1450",
+ "frc5881",
+ "frc371"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458398040,
+ "predicted_time": 0,
+ "actual_time": 1458397555,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm66",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 66,
+ "alliances": {
+ "red": {
+ "score": 59,
+ "team_keys": [
+ "frc250",
+ "frc5585",
+ "frc4930"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 57,
+ "team_keys": [
+ "frc4203",
+ "frc2791",
+ "frc229"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458398520,
+ "predicted_time": 0,
+ "actual_time": 1458398075,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm67",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 67,
+ "alliances": {
+ "red": {
+ "score": 97,
+ "team_keys": [
+ "frc333",
+ "frc3044",
+ "frc5964"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 92,
+ "team_keys": [
+ "frc4481",
+ "frc5943",
+ "frc527"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458399000,
+ "predicted_time": 0,
+ "actual_time": 1458398523,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm68",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 68,
+ "alliances": {
+ "red": {
+ "score": 76,
+ "team_keys": [
+ "frc5236",
+ "frc1493",
+ "frc1450"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 80,
+ "team_keys": [
+ "frc4856",
+ "frc358",
+ "frc1665"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458399480,
+ "predicted_time": 0,
+ "actual_time": 1458398992,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm69",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 69,
+ "alliances": {
+ "red": {
+ "score": 101,
+ "team_keys": [
+ "frc2791",
+ "frc20",
+ "frc359"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 40,
+ "team_keys": [
+ "frc5879",
+ "frc5149",
+ "frc229"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458399960,
+ "predicted_time": 0,
+ "actual_time": 1458399575,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm7",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 7,
+ "alliances": {
+ "red": {
+ "score": 64,
+ "team_keys": [
+ "frc4508",
+ "frc5943",
+ "frc1450"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 103,
+ "team_keys": [
+ "frc5240",
+ "frc48",
+ "frc145"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458309060,
+ "predicted_time": 0,
+ "actual_time": 1458309624,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm70",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 70,
+ "alliances": {
+ "red": {
+ "score": 83,
+ "team_keys": [
+ "frc1551",
+ "frc5585",
+ "frc3003"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 96,
+ "team_keys": [
+ "frc5881",
+ "frc5254",
+ "frc5240"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458400620,
+ "predicted_time": 0,
+ "actual_time": 1458400008,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm71",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 71,
+ "alliances": {
+ "red": {
+ "score": 30,
+ "team_keys": [
+ "frc4203",
+ "frc371",
+ "frc48"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 94,
+ "team_keys": [
+ "frc4508",
+ "frc4093",
+ "frc3419"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458401100,
+ "predicted_time": 0,
+ "actual_time": 1458400865,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm72",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 72,
+ "alliances": {
+ "red": {
+ "score": 74,
+ "team_keys": [
+ "frc4930",
+ "frc663",
+ "frc145"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 103,
+ "team_keys": [
+ "frc250",
+ "frc3624",
+ "frc3990"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458401580,
+ "predicted_time": 0,
+ "actual_time": 1458401706,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm8",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 8,
+ "alliances": {
+ "red": {
+ "score": 90,
+ "team_keys": [
+ "frc5254",
+ "frc5236",
+ "frc4930"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 74,
+ "team_keys": [
+ "frc1493",
+ "frc5585",
+ "frc3419"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458309540,
+ "predicted_time": 0,
+ "actual_time": 1458310026,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_qm9",
+ "comp_level": "qm",
+ "set_number": 1,
+ "match_number": 9,
+ "alliances": {
+ "red": {
+ "score": 64,
+ "team_keys": [
+ "frc5964",
+ "frc229",
+ "frc358"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 52,
+ "team_keys": [
+ "frc3003",
+ "frc333",
+ "frc5149"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458310020,
+ "predicted_time": 0,
+ "actual_time": 1458310411,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_sf1m1",
+ "comp_level": "sf",
+ "set_number": 1,
+ "match_number": 1,
+ "alliances": {
+ "red": {
+ "score": 164,
+ "team_keys": [
+ "frc3990",
+ "frc359",
+ "frc4508"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 147,
+ "team_keys": [
+ "frc5240",
+ "frc3419",
+ "frc663"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458414720,
+ "predicted_time": 0,
+ "actual_time": 1458414299,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_sf1m2",
+ "comp_level": "sf",
+ "set_number": 1,
+ "match_number": 2,
+ "alliances": {
+ "red": {
+ "score": 179,
+ "team_keys": [
+ "frc3990",
+ "frc359",
+ "frc4508"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 153,
+ "team_keys": [
+ "frc5240",
+ "frc3419",
+ "frc663"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458415560,
+ "predicted_time": 0,
+ "actual_time": 1458415297,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_sf2m1",
+ "comp_level": "sf",
+ "set_number": 2,
+ "match_number": 1,
+ "alliances": {
+ "red": {
+ "score": 107,
+ "team_keys": [
+ "frc20",
+ "frc5254",
+ "frc229"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 111,
+ "team_keys": [
+ "frc2791",
+ "frc5236",
+ "frc3624"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "blue",
+ "event_key": "2016nytr",
+ "time": 1458415140,
+ "predicted_time": 0,
+ "actual_time": 1458414793,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_sf2m2",
+ "comp_level": "sf",
+ "set_number": 2,
+ "match_number": 2,
+ "alliances": {
+ "red": {
+ "score": 149,
+ "team_keys": [
+ "frc20",
+ "frc5254",
+ "frc1665"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 106,
+ "team_keys": [
+ "frc2791",
+ "frc5236",
+ "frc3624"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458415980,
+ "predicted_time": 0,
+ "actual_time": 1458415857,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ },
+ {
+ "Key": "2016nytr_sf2m3",
+ "comp_level": "sf",
+ "set_number": 2,
+ "match_number": 3,
+ "alliances": {
+ "red": {
+ "score": 149,
+ "team_keys": [
+ "frc20",
+ "frc5254",
+ "frc1665"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ },
+ "blue": {
+ "score": 90,
+ "team_keys": [
+ "frc2791",
+ "frc5236",
+ "frc3624"
+ ],
+ "surrogate_team_keys": [],
+ "dq_team_keys": []
+ }
+ },
+ "winning_alliance": "red",
+ "event_key": "2016nytr",
+ "time": 1458417180,
+ "predicted_time": 0,
+ "actual_time": 1458416630,
+ "post_result_time": 0,
+ "score_breakdowns": {
+ "blue": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ },
+ "red": {
+ "taxiRobot1": "",
+ "endgameRobot1": "",
+ "taxiRobot2": "",
+ "endgameRobot2": "",
+ "taxiRobot3": "",
+ "endgameRobot3": "",
+ "autoCargoLowerNear": 0,
+ "autoCargoLowerFar": 0,
+ "autoCargoLowerBlue": 0,
+ "autoCargoLowerRed": 0,
+ "autoCargoUpperNear": 0,
+ "autoCargoUpperFar": 0,
+ "autoCargoUpperBlue": 0,
+ "autoCargoUpperRed": 0,
+ "autoCargoTotal": 0,
+ "teleopCargoLowerNear": 0,
+ "teleopCargoLowerFar": 0,
+ "teleopCargoLowerBlue": 0,
+ "teleopCargoLowerRed": 0,
+ "teleopCargoUpperNear": 0,
+ "teleopCargoUpperFar": 0,
+ "teleopCargoUpperBlue": 0,
+ "teleopCargoUpperRed": 0,
+ "teleopCargoTotal": 0,
+ "matchCargoTotal": 0,
+ "autoTaxiPoints": 0,
+ "autoCargoPoints": 0,
+ "autoPoints": 0,
+ "quintetAchieved": false,
+ "teleopCargoPoints": 0,
+ "endgamePoints": 0,
+ "teleopPoints": 0,
+ "cargoBonusRankingPoint": false,
+ "hangarBonusRankingPoint": false,
+ "foulCount": false,
+ "techFoulCount": 0,
+ "adjustPoints": 0,
+ "foulPoints": 0,
+ "rp": 0,
+ "totalPoints": 0
+ }
+ }
+ }
+]
diff --git a/scouting/webserver/BUILD b/scouting/webserver/BUILD
index 66db8e8..745852a 100644
--- a/scouting/webserver/BUILD
+++ b/scouting/webserver/BUILD
@@ -8,6 +8,7 @@
visibility = ["//visibility:private"],
deps = [
"//scouting/db",
+ "//scouting/scraping",
"//scouting/webserver/requests",
"//scouting/webserver/server",
"//scouting/webserver/static",
diff --git a/scouting/webserver/main.go b/scouting/webserver/main.go
index 3c699fd..94e0222 100644
--- a/scouting/webserver/main.go
+++ b/scouting/webserver/main.go
@@ -1,6 +1,7 @@
package main
import (
+ "errors"
"flag"
"fmt"
"io/ioutil"
@@ -11,6 +12,7 @@
"syscall"
"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"
"github.com/frc971/971-Robot-Code/scouting/webserver/server"
"github.com/frc971/971-Robot-Code/scouting/webserver/static"
@@ -40,6 +42,10 @@
portPtr := flag.Int("port", 8080, "The port number to bind to.")
dirPtr := flag.String("directory", ".", "The directory to serve at /.")
dbPathPtr := flag.String("database", getDefaultDatabasePath(), "The path to the database.")
+ blueAllianceConfigPtr := flag.String("tba_config", "",
+ "The path to your The Blue Alliance JSON config. "+
+ "It needs an \"api_key\" field with your TBA API key. "+
+ "Optionally, it can have a \"url\" field with the TBA API base URL.")
flag.Parse()
database, err := db.NewDatabase(*dbPathPtr)
@@ -47,9 +53,16 @@
log.Fatal("Failed to connect to database: ", err)
}
+ scrapeMatchList := func(year int32, eventCode string) ([]scraping.Match, error) {
+ if *blueAllianceConfigPtr == "" {
+ return nil, errors.New("Cannot scrape TBA's match list without a config file.")
+ }
+ return scraping.AllMatches(year, eventCode, *blueAllianceConfigPtr)
+ }
+
scoutingServer := server.NewScoutingServer()
static.ServePages(scoutingServer, *dirPtr)
- requests.HandleRequests(database, scoutingServer)
+ requests.HandleRequests(database, scrapeMatchList, scoutingServer)
scoutingServer.Start(*portPtr)
fmt.Println("Serving", *dirPtr, "on port", *portPtr)
diff --git a/scouting/webserver/requests/BUILD b/scouting/webserver/requests/BUILD
index 15e4c05..df487f2 100644
--- a/scouting/webserver/requests/BUILD
+++ b/scouting/webserver/requests/BUILD
@@ -8,7 +8,16 @@
visibility = ["//visibility:public"],
deps = [
"//scouting/db",
+ "//scouting/scraping",
"//scouting/webserver/requests/messages:error_response_go_fbs",
+ "//scouting/webserver/requests/messages:refresh_match_list_go_fbs",
+ "//scouting/webserver/requests/messages:refresh_match_list_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_all_matches_go_fbs",
+ "//scouting/webserver/requests/messages:request_all_matches_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_data_scouting_go_fbs",
+ "//scouting/webserver/requests/messages:request_data_scouting_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_matches_for_team_go_fbs",
+ "//scouting/webserver/requests/messages:request_matches_for_team_response_go_fbs",
"//scouting/webserver/requests/messages:submit_data_scouting_go_fbs",
"//scouting/webserver/requests/messages:submit_data_scouting_response_go_fbs",
"//scouting/webserver/server",
@@ -23,7 +32,17 @@
target_compatible_with = ["@platforms//cpu:x86_64"],
deps = [
"//scouting/db",
+ "//scouting/scraping",
+ "//scouting/webserver/requests/debug",
"//scouting/webserver/requests/messages:error_response_go_fbs",
+ "//scouting/webserver/requests/messages:refresh_match_list_go_fbs",
+ "//scouting/webserver/requests/messages:refresh_match_list_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_all_matches_go_fbs",
+ "//scouting/webserver/requests/messages:request_all_matches_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_data_scouting_go_fbs",
+ "//scouting/webserver/requests/messages:request_data_scouting_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_matches_for_team_go_fbs",
+ "//scouting/webserver/requests/messages:request_matches_for_team_response_go_fbs",
"//scouting/webserver/requests/messages:submit_data_scouting_go_fbs",
"//scouting/webserver/requests/messages:submit_data_scouting_response_go_fbs",
"//scouting/webserver/server",
diff --git a/scouting/webserver/requests/debug/BUILD b/scouting/webserver/requests/debug/BUILD
index cfeee2f..402503f 100644
--- a/scouting/webserver/requests/debug/BUILD
+++ b/scouting/webserver/requests/debug/BUILD
@@ -8,6 +8,10 @@
visibility = ["//visibility:public"],
deps = [
"//scouting/webserver/requests/messages:error_response_go_fbs",
+ "//scouting/webserver/requests/messages:refresh_match_list_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_all_matches_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_data_scouting_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_matches_for_team_response_go_fbs",
"//scouting/webserver/requests/messages:submit_data_scouting_response_go_fbs",
],
)
diff --git a/scouting/webserver/requests/debug/cli/BUILD b/scouting/webserver/requests/debug/cli/BUILD
index aba9177..903f8c8 100644
--- a/scouting/webserver/requests/debug/cli/BUILD
+++ b/scouting/webserver/requests/debug/cli/BUILD
@@ -10,7 +10,10 @@
importpath = "github.com/frc971/971-Robot-Code/scouting/webserver/requests/debug/cli",
target_compatible_with = ["@platforms//cpu:x86_64"],
visibility = ["//visibility:private"],
- deps = ["//scouting/webserver/requests/debug"],
+ deps = [
+ "//scouting/webserver/requests/debug",
+ "@com_github_davecgh_go_spew//spew",
+ ],
)
go_binary(
@@ -27,6 +30,7 @@
],
data = [
":cli",
+ "//scouting/scraping:test_data",
"//scouting/webserver",
],
)
diff --git a/scouting/webserver/requests/debug/cli/cli_test.py b/scouting/webserver/requests/debug/cli/cli_test.py
index 87c22c0..a737d59 100644
--- a/scouting/webserver/requests/debug/cli/cli_test.py
+++ b/scouting/webserver/requests/debug/cli/cli_test.py
@@ -1,5 +1,8 @@
+# TODO(phil): Rewrite this in Go.
+
import json
import os
+import re
from pathlib import Path
import shutil
import socket
@@ -8,11 +11,10 @@
from typing import Any, Dict, List
import unittest
-def write_json(content: Dict[str, Any]):
+def write_json_request(content: Dict[str, Any]):
"""Writes a JSON file with the specified dict content."""
json_path = Path(os.environ["TEST_TMPDIR"]) / "test.json"
- with open(json_path, "w") as file:
- file.write(json.dumps(content))
+ json_path.write_text(json.dumps(content))
return json_path
def run_debug_cli(args: List[str]):
@@ -28,28 +30,81 @@
run_result.stderr.decode("utf-8"),
)
+def wait_for_server(port: int):
+ """Waits for the server at the specified port to respond to TCP connections."""
+ while True:
+ try:
+ connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ connection.connect(("localhost", port))
+ connection.close()
+ break
+ except ConnectionRefusedError:
+ connection.close()
+ time.sleep(0.01)
+
+
class TestDebugCli(unittest.TestCase):
def setUp(self):
- self.webserver = subprocess.Popen(["scouting/webserver/webserver_/webserver"])
+ tmpdir = Path(os.environ["TEST_TMPDIR"]) / "temp"
+ try:
+ shutil.rmtree(tmpdir)
+ except FileNotFoundError:
+ pass
+ os.mkdir(tmpdir)
- # Wait for the server to respond to requests.
- while True:
- try:
- connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- connection.connect(("localhost", 8080))
- connection.close()
- break
- except ConnectionRefusedError:
- connection.close()
- time.sleep(0.01)
+ # Copy the test data into place so that the final API call can be
+ # emulated.
+ tba_api_dir = tmpdir / "api" / "v3" / "event" / "1234event_key"
+ os.makedirs(tba_api_dir)
+ (tba_api_dir / "matches").write_text(
+ Path("scouting/scraping/test_data/2016_nytr.json").read_text()
+ )
+
+ # Create a fake TBA server to serve the static match list.
+ self.fake_tba_api = subprocess.Popen(
+ ["python3", "-m", "http.server", "7000"],
+ cwd=tmpdir,
+ )
+
+ # Configure the scouting webserver to scrape data from our fake TBA
+ # server.
+ scouting_config = tmpdir / "scouting_config.json"
+ scouting_config.write_text(json.dumps({
+ "api_key": "dummy_key_that_is_not_actually_used_in_this_test",
+ "base_url": "http://localhost:7000",
+ }))
+
+ # Run the scouting webserver.
+ self.webserver = subprocess.Popen([
+ "scouting/webserver/webserver_/webserver",
+ "-port=8080",
+ "-database=%s/database.db" % tmpdir,
+ "-tba_config=%s/scouting_config.json" % tmpdir,
+ ])
+
+ # Wait for the servers to be reachable.
+ wait_for_server(7000)
+ wait_for_server(8080)
def tearDown(self):
+ self.fake_tba_api.terminate()
self.webserver.terminate()
+ self.fake_tba_api.wait()
self.webserver.wait()
+ def refresh_match_list(self):
+ """Triggers the webserver to fetch the match list."""
+ json_path = write_json_request({
+ "year": 1234,
+ "event_code": "event_key",
+ })
+ exit_code, stdout, stderr = run_debug_cli(["-refreshMatchList", json_path])
+ self.assertEqual(exit_code, 0, stderr)
+ self.assertIn("(refresh_match_list_response.RefreshMatchListResponseT)", stdout)
+
def test_submit_data_scouting(self):
- json_path = write_json({
+ json_path = write_json_request({
"team": 971,
"match": 42,
"missed_shots_auto": 9971,
@@ -67,5 +122,38 @@
self.assertEqual(exit_code, 1)
self.assertIn("/requests/submit/data_scouting returned 501 Not Implemented", stderr)
+ def test_request_all_matches(self):
+ self.refresh_match_list()
+
+ # RequestAllMatches has no fields.
+ json_path = write_json_request({})
+ exit_code, stdout, stderr = run_debug_cli(["-requestAllMatches", json_path])
+
+ self.assertEqual(exit_code, 0, stderr)
+ self.assertIn("MatchList: ([]*request_all_matches_response.MatchT) (len=90 cap=90) {", stdout)
+ self.assertEqual(stdout.count("MatchNumber:"), 90)
+
+ def test_request_matches_for_team(self):
+ self.refresh_match_list()
+
+ json_path = write_json_request({
+ "team": 4856,
+ })
+ exit_code, stdout, stderr = run_debug_cli(["-requestMatchesForTeam", json_path])
+
+ # Team 4856 has 12 matches.
+ self.assertEqual(exit_code, 0, stderr)
+ self.assertIn("MatchList: ([]*request_matches_for_team_response.MatchT) (len=12 cap=12) {", stdout)
+ self.assertEqual(stdout.count("MatchNumber:"), 12)
+ self.assertEqual(len(re.findall(r": \(int32\) 4856[,\n]", stdout)), 12)
+
+ def test_request_data_scouting(self):
+ json_path = write_json_request({})
+ exit_code, stdout, stderr = run_debug_cli(["-requestDataScouting", json_path])
+
+ # TODO(phil): Actually add data here before querying it.
+ self.assertEqual(exit_code, 0, stderr)
+ self.assertIn("(request_data_scouting_response.RequestDataScoutingResponseT)", stdout)
+
if __name__ == "__main__":
unittest.main()
diff --git a/scouting/webserver/requests/debug/cli/main.go b/scouting/webserver/requests/debug/cli/main.go
index ac24b25..03032be 100644
--- a/scouting/webserver/requests/debug/cli/main.go
+++ b/scouting/webserver/requests/debug/cli/main.go
@@ -11,6 +11,7 @@
"os/exec"
"path/filepath"
+ "github.com/davecgh/go-spew/spew"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/debug"
)
@@ -50,9 +51,9 @@
// Execute the `flatc` command.
flatcCommand := exec.Command(absFlatcPath, "--binary", absFbsPath, jsonSymlink)
flatcCommand.Dir = dir
- err = flatcCommand.Run()
+ output, err := flatcCommand.CombinedOutput()
if err != nil {
- log.Fatal("Failed to execute flatc: ", err)
+ log.Fatal("Failed to execute flatc: ", err, ": ", string(output))
}
// Read the serialized flatbuffer and return it.
@@ -70,6 +71,14 @@
"The end point where the server is listening.")
submitDataScoutingPtr := flag.String("submitDataScouting", "",
"If specified, parse the file as a SubmitDataScouting JSON request.")
+ requestAllMatchesPtr := flag.String("requestAllMatches", "",
+ "If specified, parse the file as a RequestAllMatches JSON request.")
+ requestMatchesForTeamPtr := flag.String("requestMatchesForTeam", "",
+ "If specified, parse the file as a RequestMatchesForTeam JSON request.")
+ requestDataScoutingPtr := flag.String("requestDataScouting", "",
+ "If specified, parse the file as a RequestDataScouting JSON request.")
+ refreshMatchListPtr := flag.String("refreshMatchList", "",
+ "If specified, parse the file as a RefreshMatchList JSON request.")
flag.Parse()
// Handle the actual arguments.
@@ -82,6 +91,50 @@
if err != nil {
log.Fatal("Failed SubmitDataScouting: ", err)
}
- log.Printf("%+v", response)
+ spew.Dump(*response)
+ }
+ if *requestAllMatchesPtr != "" {
+ log.Printf("Sending RequestAllMatches to %s", *addressPtr)
+ binaryRequest := parseJson(
+ "scouting/webserver/requests/messages/request_all_matches.fbs",
+ *requestAllMatchesPtr)
+ response, err := debug.RequestAllMatches(*addressPtr, binaryRequest)
+ if err != nil {
+ log.Fatal("Failed RequestAllMatches: ", err)
+ }
+ spew.Dump(*response)
+ }
+ if *requestMatchesForTeamPtr != "" {
+ log.Printf("Sending RequestMatchesForTeam to %s", *addressPtr)
+ binaryRequest := parseJson(
+ "scouting/webserver/requests/messages/request_matches_for_team.fbs",
+ *requestMatchesForTeamPtr)
+ response, err := debug.RequestMatchesForTeam(*addressPtr, binaryRequest)
+ if err != nil {
+ log.Fatal("Failed RequestMatchesForTeam: ", err)
+ }
+ spew.Dump(*response)
+ }
+ if *requestDataScoutingPtr != "" {
+ log.Printf("Sending RequestDataScouting to %s", *addressPtr)
+ binaryRequest := parseJson(
+ "scouting/webserver/requests/messages/request_data_scouting.fbs",
+ *requestDataScoutingPtr)
+ response, err := debug.RequestDataScouting(*addressPtr, binaryRequest)
+ if err != nil {
+ log.Fatal("Failed RequestDataScouting: ", err)
+ }
+ spew.Dump(*response)
+ }
+ if *refreshMatchListPtr != "" {
+ log.Printf("Sending RefreshMatchList to %s", *addressPtr)
+ binaryRequest := parseJson(
+ "scouting/webserver/requests/messages/refresh_match_list.fbs",
+ *refreshMatchListPtr)
+ response, err := debug.RefreshMatchList(*addressPtr, binaryRequest)
+ if err != nil {
+ log.Fatal("Failed RefreshMatchList: ", err)
+ }
+ spew.Dump(*response)
}
}
diff --git a/scouting/webserver/requests/debug/debug.go b/scouting/webserver/requests/debug/debug.go
index dd70c1b..81be3d1 100644
--- a/scouting/webserver/requests/debug/debug.go
+++ b/scouting/webserver/requests/debug/debug.go
@@ -9,11 +9,19 @@
"net/http"
"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_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting_response"
)
// Use aliases to make the rest of the code more readable.
type SubmitDataScoutingResponseT = submit_data_scouting_response.SubmitDataScoutingResponseT
+type RequestAllMatchesResponseT = request_all_matches_response.RequestAllMatchesResponseT
+type RequestMatchesForTeamResponseT = request_matches_for_team_response.RequestMatchesForTeamResponseT
+type RequestDataScoutingResponseT = request_data_scouting_response.RequestDataScoutingResponseT
+type RefreshMatchListResponseT = refresh_match_list_response.RefreshMatchListResponseT
// A struct that can be used as an `error`. It contains information about the
// why the server was unhappy and what the corresponding request was.
@@ -85,3 +93,51 @@
response := submit_data_scouting_response.GetRootAsSubmitDataScoutingResponse(responseBytes, 0)
return response.UnPack(), nil
}
+
+// Sends a `RequestAllMatches` message to the server and returns the
+// deserialized response.
+func RequestAllMatches(server string, requestBytes []byte) (*RequestAllMatchesResponseT, error) {
+ responseBytes, err := performPost(server+"/requests/request/all_matches", requestBytes)
+ if err != nil {
+ return nil, err
+ }
+ log.Printf("Parsing RequestAllMatchesResponse")
+ response := request_all_matches_response.GetRootAsRequestAllMatchesResponse(responseBytes, 0)
+ return response.UnPack(), nil
+}
+
+// Sends a `RequestMatchesForTeam` message to the server and returns the
+// deserialized response.
+func RequestMatchesForTeam(server string, requestBytes []byte) (*RequestMatchesForTeamResponseT, error) {
+ responseBytes, err := performPost(server+"/requests/request/matches_for_team", requestBytes)
+ if err != nil {
+ return nil, err
+ }
+ log.Printf("Parsing RequestMatchesForTeamResponse")
+ response := request_matches_for_team_response.GetRootAsRequestMatchesForTeamResponse(responseBytes, 0)
+ return response.UnPack(), nil
+}
+
+// Sends a `RequestDataScouting` message to the server and returns the
+// deserialized response.
+func RequestDataScouting(server string, requestBytes []byte) (*RequestDataScoutingResponseT, error) {
+ responseBytes, err := performPost(server+"/requests/request/data_scouting", requestBytes)
+ if err != nil {
+ return nil, err
+ }
+ log.Printf("Parsing RequestDataScoutingResponse")
+ response := request_data_scouting_response.GetRootAsRequestDataScoutingResponse(responseBytes, 0)
+ return response.UnPack(), nil
+}
+
+// Sends a `RefreshMatchList` message to the server and returns the
+// deserialized response.
+func RefreshMatchList(server string, requestBytes []byte) (*RefreshMatchListResponseT, error) {
+ responseBytes, err := performPost(server+"/requests/refresh_match_list", requestBytes)
+ if err != nil {
+ return nil, err
+ }
+ log.Printf("Parsing RefreshMatchListResponse")
+ response := refresh_match_list_response.GetRootAsRefreshMatchListResponse(responseBytes, 0)
+ return response.UnPack(), nil
+}
diff --git a/scouting/webserver/requests/messages/BUILD b/scouting/webserver/requests/messages/BUILD
index 53ceab2..c27f730 100644
--- a/scouting/webserver/requests/messages/BUILD
+++ b/scouting/webserver/requests/messages/BUILD
@@ -10,6 +10,8 @@
"request_matches_for_team_response",
"request_data_scouting",
"request_data_scouting_response",
+ "refresh_match_list",
+ "refresh_match_list_response",
)
filegroup(
diff --git a/scouting/webserver/requests/messages/refresh_match_list.fbs b/scouting/webserver/requests/messages/refresh_match_list.fbs
new file mode 100644
index 0000000..c4384c7
--- /dev/null
+++ b/scouting/webserver/requests/messages/refresh_match_list.fbs
@@ -0,0 +1,8 @@
+namespace scouting.webserver.requests;
+
+table RefreshMatchList {
+ year: int (id: 0);
+ event_code: string (id: 1);
+}
+
+root_type RefreshMatchList;
diff --git a/scouting/webserver/requests/messages/refresh_match_list_response.fbs b/scouting/webserver/requests/messages/refresh_match_list_response.fbs
new file mode 100644
index 0000000..ba80272
--- /dev/null
+++ b/scouting/webserver/requests/messages/refresh_match_list_response.fbs
@@ -0,0 +1,6 @@
+namespace scouting.webserver.requests;
+
+table RefreshMatchListResponse {
+}
+
+root_type RefreshMatchListResponse;
diff --git a/scouting/webserver/requests/messages/request_all_matches.fbs b/scouting/webserver/requests/messages/request_all_matches.fbs
index 1d4acc2..2ec9aa1 100644
--- a/scouting/webserver/requests/messages/request_all_matches.fbs
+++ b/scouting/webserver/requests/messages/request_all_matches.fbs
@@ -1,6 +1,6 @@
namespace scouting.webserver.requests;
-table RequestMatchList {
+table RequestAllMatches {
}
-root_type RequestMatchList;
\ No newline at end of file
+root_type RequestAllMatches;
diff --git a/scouting/webserver/requests/messages/request_all_matches_response.fbs b/scouting/webserver/requests/messages/request_all_matches_response.fbs
index d4a1658..90401e3 100644
--- a/scouting/webserver/requests/messages/request_all_matches_response.fbs
+++ b/scouting/webserver/requests/messages/request_all_matches_response.fbs
@@ -12,8 +12,8 @@
b3:int (id: 8);
}
-table RequestMatchListResponse {
+table RequestAllMatchesResponse {
match_list:[Match] (id:0);
}
-root_type RequestMatchListResponse;
\ No newline at end of file
+root_type RequestAllMatchesResponse;
diff --git a/scouting/webserver/requests/messages/request_data_scouting.fbs b/scouting/webserver/requests/messages/request_data_scouting.fbs
index 45f6308..884c1a6 100644
--- a/scouting/webserver/requests/messages/request_data_scouting.fbs
+++ b/scouting/webserver/requests/messages/request_data_scouting.fbs
@@ -1,7 +1,7 @@
namespace scouting.webserver.requests;
-table QueryDataScouting {
+table RequestDataScouting {
// TODO: Implement this.
}
-root_type QueryDataScouting;
\ No newline at end of file
+root_type RequestDataScouting;
diff --git a/scouting/webserver/requests/messages/request_data_scouting_response.fbs b/scouting/webserver/requests/messages/request_data_scouting_response.fbs
index 83f5cd0..e30ab42 100644
--- a/scouting/webserver/requests/messages/request_data_scouting_response.fbs
+++ b/scouting/webserver/requests/messages/request_data_scouting_response.fbs
@@ -1,6 +1,6 @@
namespace scouting.webserver.requests;
-struct Stats {
+table Stats {
team:int (id: 0);
match:int (id: 1);
missed_shots_auto:int (id: 2);
@@ -13,8 +13,8 @@
climbing:int (id:9);
}
-table QueryDataScoutingResponse {
+table RequestDataScoutingResponse {
stats_list:[Stats] (id:0);
}
-root_type QueryDataScoutingResponse;
\ No newline at end of file
+root_type RequestDataScoutingResponse;
diff --git a/scouting/webserver/requests/messages/request_matches_for_team.fbs b/scouting/webserver/requests/messages/request_matches_for_team.fbs
index 388533e..dd1b217 100644
--- a/scouting/webserver/requests/messages/request_matches_for_team.fbs
+++ b/scouting/webserver/requests/messages/request_matches_for_team.fbs
@@ -1,7 +1,7 @@
namespace scouting.webserver.requests;
-table QueryMatchList {
+table RequestMatchesForTeam {
team:int (id: 0);
}
-root_type QueryMatchList;
\ No newline at end of file
+root_type RequestMatchesForTeam;
diff --git a/scouting/webserver/requests/messages/request_matches_for_team_response.fbs b/scouting/webserver/requests/messages/request_matches_for_team_response.fbs
index 7345520..cbb1895 100644
--- a/scouting/webserver/requests/messages/request_matches_for_team_response.fbs
+++ b/scouting/webserver/requests/messages/request_matches_for_team_response.fbs
@@ -13,8 +13,8 @@
}
//TODO(Sabina): de-duplicate the Match struct in request_all_matches
-table QueryMatchListResponse {
+table RequestMatchesForTeamResponse {
match_list:[Match] (id:0);
}
-root_type QueryMatchListResponse;
\ No newline at end of file
+root_type RequestMatchesForTeamResponse;
diff --git a/scouting/webserver/requests/messages/submit_data_scouting.fbs b/scouting/webserver/requests/messages/submit_data_scouting.fbs
index 6213dd5..755e70b 100644
--- a/scouting/webserver/requests/messages/submit_data_scouting.fbs
+++ b/scouting/webserver/requests/messages/submit_data_scouting.fbs
@@ -9,7 +9,17 @@
missed_shots_tele:int (id: 5);
upper_goal_tele:int (id:6);
lower_goal_tele:int (id:7);
+ // The rating that is used to rate the defense that this robot played on
+ // other robots.
+ // TODO: Document what the different values mean. E.g. 0 means no defense
+ // played?
defense_rating:int (id:8);
+ // The amount of defense that other robots played on this robot.
+ // TODO: Document what the different values mean. E.g. 0 means no defense
+ // played against this robot?
+ defense_received_rating:int (id:10);
+ // The rating that this robot gets for its climbing.
+ // TODO: Change into an enum to make the different values self-documenting.
climbing:int (id:9);
}
diff --git a/scouting/webserver/requests/requests.go b/scouting/webserver/requests/requests.go
index 2462ccb..93ee128 100644
--- a/scouting/webserver/requests/requests.go
+++ b/scouting/webserver/requests/requests.go
@@ -1,18 +1,40 @@
package requests
import (
+ "errors"
"fmt"
"io"
"net/http"
+ "strconv"
+ "strings"
"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/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_matches"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting"
_ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/server"
flatbuffers "github.com/google/flatbuffers/go"
)
+type SubmitDataScouting = submit_data_scouting.SubmitDataScouting
+type RequestAllMatches = request_all_matches.RequestAllMatches
+type RequestAllMatchesResponseT = request_all_matches_response.RequestAllMatchesResponseT
+type RequestMatchesForTeam = request_matches_for_team.RequestMatchesForTeam
+type RequestMatchesForTeamResponseT = request_matches_for_team_response.RequestMatchesForTeamResponseT
+type RequestDataScouting = request_data_scouting.RequestDataScouting
+type RequestDataScoutingResponseT = request_data_scouting_response.RequestDataScoutingResponseT
+type RefreshMatchList = refresh_match_list.RefreshMatchList
+type RefreshMatchListResponseT = refresh_match_list_response.RefreshMatchListResponseT
+
// The interface we expect the database abstraction to conform to.
// We use an interface here because it makes unit testing easier.
type Database interface {
@@ -20,10 +42,12 @@
AddToStats(db.Stats) error
ReturnMatches() ([]db.Match, error)
ReturnStats() ([]db.Stats, error)
- QueryMatches(int) ([]db.Match, error)
+ QueryMatches(int32) ([]db.Match, error)
QueryStats(int) ([]db.Stats, error)
}
+type ScrapeMatchList func(int32, string) ([]scraping.Match, error)
+
// Handles unknown requests. Just returns a 404.
func unknown(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusNotFound)
@@ -43,7 +67,7 @@
}
// TODO(phil): Can we turn this into a generic?
-func parseSubmitDataScouting(w http.ResponseWriter, buf []byte) (*submit_data_scouting.SubmitDataScouting, bool) {
+func parseSubmitDataScouting(w http.ResponseWriter, buf []byte) (*SubmitDataScouting, bool) {
success := true
defer func() {
if r := recover(); r != nil {
@@ -79,7 +103,283 @@
respondNotImplemented(w)
}
-func HandleRequests(db Database, scoutingServer server.ScoutingServer) {
+// TODO(phil): Can we turn this into a generic?
+func parseRequestAllMatches(w http.ResponseWriter, buf []byte) (*RequestAllMatches, bool) {
+ success := true
+ defer func() {
+ if r := recover(); r != nil {
+ respondWithError(w, http.StatusBadRequest, fmt.Sprintf("Failed to parse SubmitDataScouting: %v", r))
+ success = false
+ }
+ }()
+ result := request_all_matches.GetRootAsRequestAllMatches(buf, 0)
+ return result, success
+}
+
+// Handles a RequestAllMaches request.
+type requestAllMatchesHandler struct {
+ db Database
+}
+
+func (handler requestAllMatchesHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ requestBytes, err := io.ReadAll(req.Body)
+ if err != nil {
+ respondWithError(w, http.StatusBadRequest, fmt.Sprint("Failed to read request bytes:", err))
+ return
+ }
+
+ _, success := parseRequestAllMatches(w, requestBytes)
+ if !success {
+ return
+ }
+
+ matches, err := handler.db.ReturnMatches()
+ if err != nil {
+ respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Faled to query database: ", err))
+ return
+ }
+
+ var response RequestAllMatchesResponseT
+ for _, match := range matches {
+ response.MatchList = append(response.MatchList, &request_all_matches_response.MatchT{
+ MatchNumber: match.MatchNumber,
+ Round: match.Round,
+ CompLevel: match.CompLevel,
+ R1: match.R1,
+ R2: match.R2,
+ R3: match.R3,
+ B1: match.B1,
+ B2: match.B2,
+ B3: match.B3,
+ })
+ }
+
+ builder := flatbuffers.NewBuilder(50 * 1024)
+ builder.Finish((&response).Pack(builder))
+ w.Write(builder.FinishedBytes())
+}
+
+// TODO(phil): Can we turn this into a generic?
+func parseRequestMatchesForTeam(w http.ResponseWriter, buf []byte) (*RequestMatchesForTeam, bool) {
+ success := true
+ defer func() {
+ if r := recover(); r != nil {
+ respondWithError(w, http.StatusBadRequest, fmt.Sprintf("Failed to parse SubmitDataScouting: %v", r))
+ success = false
+ }
+ }()
+ result := request_matches_for_team.GetRootAsRequestMatchesForTeam(buf, 0)
+ return result, success
+}
+
+// Handles a RequestMatchesForTeam request.
+type requestMatchesForTeamHandler struct {
+ db Database
+}
+
+func (handler requestMatchesForTeamHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ requestBytes, err := io.ReadAll(req.Body)
+ if err != nil {
+ respondWithError(w, http.StatusBadRequest, fmt.Sprint("Failed to read request bytes:", err))
+ return
+ }
+
+ request, success := parseRequestMatchesForTeam(w, requestBytes)
+ if !success {
+ return
+ }
+
+ matches, err := handler.db.QueryMatches(request.Team())
+ if err != nil {
+ respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Faled to query database: ", err))
+ return
+ }
+
+ var response RequestAllMatchesResponseT
+ for _, match := range matches {
+ response.MatchList = append(response.MatchList, &request_all_matches_response.MatchT{
+ MatchNumber: match.MatchNumber,
+ Round: match.Round,
+ CompLevel: match.CompLevel,
+ R1: match.R1,
+ R2: match.R2,
+ R3: match.R3,
+ B1: match.B1,
+ B2: match.B2,
+ B3: match.B3,
+ })
+ }
+
+ builder := flatbuffers.NewBuilder(50 * 1024)
+ builder.Finish((&response).Pack(builder))
+ w.Write(builder.FinishedBytes())
+}
+
+// TODO(phil): Can we turn this into a generic?
+func parseRequestDataScouting(w http.ResponseWriter, buf []byte) (*RequestDataScouting, bool) {
+ success := true
+ defer func() {
+ if r := recover(); r != nil {
+ respondWithError(w, http.StatusBadRequest, fmt.Sprintf("Failed to parse SubmitDataScouting: %v", r))
+ success = false
+ }
+ }()
+ result := request_data_scouting.GetRootAsRequestDataScouting(buf, 0)
+ return result, success
+}
+
+// Handles a RequestDataScouting request.
+type requestDataScoutingHandler struct {
+ db Database
+}
+
+func (handler requestDataScoutingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ requestBytes, err := io.ReadAll(req.Body)
+ if err != nil {
+ respondWithError(w, http.StatusBadRequest, fmt.Sprint("Failed to read request bytes:", err))
+ return
+ }
+
+ _, success := parseRequestDataScouting(w, requestBytes)
+ if !success {
+ return
+ }
+
+ stats, err := handler.db.ReturnStats()
+ if err != nil {
+ respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Faled to query database: ", err))
+ return
+ }
+
+ var response RequestDataScoutingResponseT
+ for _, stat := range stats {
+ response.StatsList = append(response.StatsList, &request_data_scouting_response.StatsT{
+ Team: stat.TeamNumber,
+ Match: stat.MatchNumber,
+ MissedShotsAuto: stat.ShotsMissedAuto,
+ UpperGoalAuto: stat.UpperGoalAuto,
+ LowerGoalAuto: stat.LowerGoalAuto,
+ MissedShotsTele: stat.ShotsMissed,
+ UpperGoalTele: stat.UpperGoalShots,
+ LowerGoalTele: stat.LowerGoalShots,
+ DefenseRating: stat.PlayedDefense,
+ Climbing: stat.Climbing,
+ })
+ }
+
+ builder := flatbuffers.NewBuilder(50 * 1024)
+ builder.Finish((&response).Pack(builder))
+ w.Write(builder.FinishedBytes())
+}
+
+// TODO(phil): Can we turn this into a generic?
+func parseRefreshMatchList(w http.ResponseWriter, buf []byte) (*RefreshMatchList, bool) {
+ success := true
+ defer func() {
+ if r := recover(); r != nil {
+ respondWithError(w, http.StatusBadRequest, fmt.Sprintf("Failed to parse RefreshMatchList: %v", r))
+ success = false
+ }
+ }()
+ result := refresh_match_list.GetRootAsRefreshMatchList(buf, 0)
+ return result, success
+}
+
+func parseTeamKey(teamKey string) (int, error) {
+ // TBA prefixes teams with "frc". Not sure why. Get rid of that.
+ teamKey = strings.TrimPrefix(teamKey, "frc")
+ return strconv.Atoi(teamKey)
+}
+
+// Parses the alliance data from the specified match and returns the three red
+// teams and the three blue teams.
+func parseTeamKeys(match *scraping.Match) ([3]int32, [3]int32, error) {
+ redKeys := match.Alliances.Red.TeamKeys
+ blueKeys := match.Alliances.Blue.TeamKeys
+
+ if len(redKeys) != 3 || len(blueKeys) != 3 {
+ return [3]int32{}, [3]int32{}, errors.New(fmt.Sprintf(
+ "Found %d red teams and %d blue teams.", len(redKeys), len(blueKeys)))
+ }
+
+ var red [3]int32
+ for i, key := range redKeys {
+ team, err := parseTeamKey(key)
+ if err != nil {
+ return [3]int32{}, [3]int32{}, errors.New(fmt.Sprintf(
+ "Failed to parse red %d team '%s' as integer: %v", i+1, key, err))
+ }
+ red[i] = int32(team)
+ }
+ var blue [3]int32
+ for i, key := range blueKeys {
+ team, err := parseTeamKey(key)
+ if err != nil {
+ return [3]int32{}, [3]int32{}, errors.New(fmt.Sprintf(
+ "Failed to parse blue %d team '%s' as integer: %v", i+1, key, err))
+ }
+ blue[i] = int32(team)
+ }
+ return red, blue, nil
+}
+
+type refreshMatchListHandler struct {
+ db Database
+ scrape ScrapeMatchList
+}
+
+func (handler refreshMatchListHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ requestBytes, err := io.ReadAll(req.Body)
+ if err != nil {
+ respondWithError(w, http.StatusBadRequest, fmt.Sprint("Failed to read request bytes:", err))
+ return
+ }
+
+ request, success := parseRefreshMatchList(w, requestBytes)
+ if !success {
+ return
+ }
+
+ matches, err := handler.scrape(request.Year(), string(request.EventCode()))
+ if err != nil {
+ respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Faled to scrape match list: ", err))
+ return
+ }
+
+ for _, match := range matches {
+ // Make sure the data is valid.
+ red, blue, err := parseTeamKeys(&match)
+ if err != nil {
+ respondWithError(w, http.StatusInternalServerError, fmt.Sprintf(
+ "TheBlueAlliance data for match %d is malformed: %v", match.MatchNumber, err))
+ return
+ }
+ // Add the match to the database.
+ handler.db.AddToMatch(db.Match{
+ MatchNumber: int32(match.MatchNumber),
+ // TODO(phil): What does Round mean?
+ Round: 1,
+ CompLevel: match.CompLevel,
+ R1: red[0],
+ R2: red[1],
+ R3: red[2],
+ B1: blue[0],
+ B2: blue[1],
+ B3: blue[2],
+ })
+ }
+
+ var response RefreshMatchListResponseT
+ builder := flatbuffers.NewBuilder(1024)
+ builder.Finish((&response).Pack(builder))
+ w.Write(builder.FinishedBytes())
+}
+
+func HandleRequests(db Database, scrape ScrapeMatchList, scoutingServer server.ScoutingServer) {
scoutingServer.HandleFunc("/requests", unknown)
scoutingServer.Handle("/requests/submit/data_scouting", submitDataScoutingHandler{db})
+ scoutingServer.Handle("/requests/request/all_matches", requestAllMatchesHandler{db})
+ scoutingServer.Handle("/requests/request/matches_for_team", requestMatchesForTeamHandler{db})
+ scoutingServer.Handle("/requests/request/data_scouting", requestDataScoutingHandler{db})
+ scoutingServer.Handle("/requests/refresh_match_list", refreshMatchListHandler{db, scrape})
}
diff --git a/scouting/webserver/requests/requests_test.go b/scouting/webserver/requests/requests_test.go
index 0125da5..999e955 100644
--- a/scouting/webserver/requests/requests_test.go
+++ b/scouting/webserver/requests/requests_test.go
@@ -4,10 +4,21 @@
"bytes"
"io"
"net/http"
+ "reflect"
"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_matches"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting"
_ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/server"
@@ -18,7 +29,7 @@
func Test404(t *testing.T) {
db := MockDatabase{}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&db, scoutingServer)
+ HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -35,7 +46,7 @@
func TestSubmitDataScoutingError(t *testing.T) {
db := MockDatabase{}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&db, scoutingServer)
+ HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -63,7 +74,7 @@
func TestSubmitDataScouting(t *testing.T) {
db := MockDatabase{}
scoutingServer := server.NewScoutingServer()
- HandleRequests(&db, scoutingServer)
+ HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
scoutingServer.Start(8080)
defer scoutingServer.Stop()
@@ -92,12 +103,258 @@
// TODO(phil): Can we use scouting/webserver/requests/debug here?
}
+// Validates that we can request the full match list.
+func TestRequestAllMatches(t *testing.T) {
+ db := MockDatabase{
+ matches: []db.Match{
+ {
+ MatchNumber: 1, Round: 1, CompLevel: "qual",
+ R1: 5, R2: 42, R3: 600, B1: 971, B2: 400, B3: 200,
+ },
+ {
+ MatchNumber: 2, Round: 1, CompLevel: "qual",
+ R1: 6, R2: 43, R3: 601, B1: 972, B2: 401, B3: 201,
+ },
+ {
+ MatchNumber: 3, Round: 1, CompLevel: "qual",
+ R1: 7, R2: 44, R3: 602, B1: 973, B2: 402, B3: 202,
+ },
+ },
+ }
+ scoutingServer := server.NewScoutingServer()
+ HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
+ scoutingServer.Start(8080)
+ defer scoutingServer.Stop()
+
+ builder := flatbuffers.NewBuilder(1024)
+ builder.Finish((&request_all_matches.RequestAllMatchesT{}).Pack(builder))
+
+ response, err := debug.RequestAllMatches("http://localhost:8080", builder.FinishedBytes())
+ if err != nil {
+ t.Fatal("Failed to request all matches: ", err)
+ }
+
+ expected := request_all_matches_response.RequestAllMatchesResponseT{
+ MatchList: []*request_all_matches_response.MatchT{
+ // MatchNumber, Round, CompLevel
+ // R1, R2, R3, B1, B2, B3
+ {
+ 1, 1, "qual",
+ 5, 42, 600, 971, 400, 200,
+ },
+ {
+ 2, 1, "qual",
+ 6, 43, 601, 972, 401, 201,
+ },
+ {
+ 3, 1, "qual",
+ 7, 44, 602, 973, 402, 202,
+ },
+ },
+ }
+ if len(expected.MatchList) != len(response.MatchList) {
+ t.Fatal("Expected ", expected, ", but got ", *response)
+ }
+ for i, match := range expected.MatchList {
+ if !reflect.DeepEqual(*match, *response.MatchList[i]) {
+ t.Fatal("Expected for match", i, ":", *match, ", but got:", *response.MatchList[i])
+ }
+ }
+}
+
+// Validates that we can request the full match list.
+func TestRequestMatchesForTeam(t *testing.T) {
+ db := MockDatabase{
+ matches: []db.Match{
+ {
+ MatchNumber: 1, Round: 1, CompLevel: "qual",
+ R1: 5, R2: 42, R3: 600, B1: 971, B2: 400, B3: 200,
+ },
+ {
+ MatchNumber: 2, Round: 1, CompLevel: "qual",
+ R1: 6, R2: 43, R3: 601, B1: 972, B2: 401, B3: 201,
+ },
+ },
+ }
+ scoutingServer := server.NewScoutingServer()
+ HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
+ scoutingServer.Start(8080)
+ defer scoutingServer.Stop()
+
+ builder := flatbuffers.NewBuilder(1024)
+ builder.Finish((&request_matches_for_team.RequestMatchesForTeamT{
+ Team: 971,
+ }).Pack(builder))
+
+ response, err := debug.RequestMatchesForTeam("http://localhost:8080", builder.FinishedBytes())
+ if err != nil {
+ t.Fatal("Failed to request all matches: ", err)
+ }
+
+ expected := request_matches_for_team_response.RequestMatchesForTeamResponseT{
+ MatchList: []*request_matches_for_team_response.MatchT{
+ // MatchNumber, Round, CompLevel
+ // R1, R2, R3, B1, B2, B3
+ {
+ 1, 1, "qual",
+ 5, 42, 600, 971, 400, 200,
+ },
+ },
+ }
+ if len(expected.MatchList) != len(response.MatchList) {
+ t.Fatal("Expected ", expected, ", but got ", *response)
+ }
+ for i, match := range expected.MatchList {
+ if !reflect.DeepEqual(*match, *response.MatchList[i]) {
+ t.Fatal("Expected for match", i, ":", *match, ", but got:", *response.MatchList[i])
+ }
+ }
+}
+
+// Validates that we can request the stats.
+func TestRequestDataScouting(t *testing.T) {
+ db := MockDatabase{
+ stats: []db.Stats{
+ {
+ TeamNumber: 971, MatchNumber: 1,
+ ShotsMissed: 1, UpperGoalShots: 2, LowerGoalShots: 3,
+ ShotsMissedAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
+ PlayedDefense: 7, Climbing: 8,
+ },
+ {
+ TeamNumber: 972, MatchNumber: 1,
+ ShotsMissed: 2, UpperGoalShots: 3, LowerGoalShots: 4,
+ ShotsMissedAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
+ PlayedDefense: 8, Climbing: 9,
+ },
+ },
+ }
+ scoutingServer := server.NewScoutingServer()
+ HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
+ scoutingServer.Start(8080)
+ defer scoutingServer.Stop()
+
+ builder := flatbuffers.NewBuilder(1024)
+ builder.Finish((&request_data_scouting.RequestDataScoutingT{}).Pack(builder))
+
+ response, err := debug.RequestDataScouting("http://localhost:8080", builder.FinishedBytes())
+ if err != nil {
+ t.Fatal("Failed to request all matches: ", err)
+ }
+
+ expected := request_data_scouting_response.RequestDataScoutingResponseT{
+ StatsList: []*request_data_scouting_response.StatsT{
+ // Team, Match,
+ // MissedShotsAuto, UpperGoalAuto, LowerGoalAuto,
+ // MissedShotsTele, UpperGoalTele, LowerGoalTele,
+ // DefenseRating, Climbing,
+ {
+ 971, 1,
+ 4, 5, 6,
+ 1, 2, 3,
+ 7, 8,
+ },
+ {
+ 972, 1,
+ 5, 6, 7,
+ 2, 3, 4,
+ 8, 9,
+ },
+ },
+ }
+ if len(expected.StatsList) != len(response.StatsList) {
+ t.Fatal("Expected ", expected, ", but got ", *response)
+ }
+ for i, match := range expected.StatsList {
+ if !reflect.DeepEqual(*match, *response.StatsList[i]) {
+ t.Fatal("Expected for stats", i, ":", *match, ", but got:", *response.StatsList[i])
+ }
+ }
+}
+
+// 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,
+ 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.Match{
+ {
+ MatchNumber: 1,
+ Round: 1,
+ CompLevel: "qual",
+ R1: 100,
+ R2: 200,
+ R3: 300,
+ B1: 101,
+ B2: 201,
+ B3: 301,
+ },
+ }
+ if !reflect.DeepEqual(expectedMatches, database.matches) {
+ t.Fatal("Expected ", expectedMatches, ", but got ", database.matches)
+ }
+}
+
// A mocked database we can use for testing. Add functionality to this as
// needed for your tests.
-type MockDatabase struct{}
+type MockDatabase struct {
+ matches []db.Match
+ stats []db.Stats
+}
-func (database *MockDatabase) AddToMatch(db.Match) error {
+func (database *MockDatabase) AddToMatch(match db.Match) error {
+ database.matches = append(database.matches, match)
return nil
}
@@ -106,17 +363,31 @@
}
func (database *MockDatabase) ReturnMatches() ([]db.Match, error) {
- return []db.Match{}, nil
+ return database.matches, nil
}
func (database *MockDatabase) ReturnStats() ([]db.Stats, error) {
- return []db.Stats{}, nil
+ return database.stats, nil
}
-func (database *MockDatabase) QueryMatches(int) ([]db.Match, error) {
- return []db.Match{}, nil
+func (database *MockDatabase) QueryMatches(requestedTeam int32) ([]db.Match, error) {
+ var matches []db.Match
+ for _, match := range database.matches {
+ for _, team := range []int32{match.R1, match.R2, match.R3, match.B1, match.B2, match.B3} {
+ if team == requestedTeam {
+ matches = append(matches, match)
+ break
+ }
+ }
+ }
+ return matches, nil
}
func (database *MockDatabase) QueryStats(int) ([]db.Stats, error) {
return []db.Stats{}, nil
}
+
+// Returns an empty match list from the fake The Blue Alliance scraping.
+func scrapeEmtpyMatchList(int32, string) ([]scraping.Match, error) {
+ return nil, nil
+}
diff --git a/scouting/www/BUILD b/scouting/www/BUILD
index aa2ad7b..39246d8 100644
--- a/scouting/www/BUILD
+++ b/scouting/www/BUILD
@@ -14,12 +14,14 @@
]),
angular_assets = glob([
"*.ng.html",
+ "*.css",
]),
compiler = "//tools:tsc_wrapped_with_angular",
target_compatible_with = ["@platforms//cpu:x86_64"],
use_angular_plugin = True,
visibility = ["//visibility:public"],
deps = [
+ "//scouting/www/entry",
"@npm//@angular/animations",
"@npm//@angular/common",
"@npm//@angular/core",
diff --git a/scouting/www/app.ng.html b/scouting/www/app.ng.html
index fb9ba26..f763b7d 100644
--- a/scouting/www/app.ng.html
+++ b/scouting/www/app.ng.html
@@ -1,3 +1,5 @@
-<h1>
- This is an app.
-</h1>
+<!--Progress Bar-->
+<!--<div class="row">
+ <h1 class="text-end">Match {{matchNumber}}, Team {{teamNumber}}</h1>
+</div>-->
+<app-entry></app-entry>
diff --git a/scouting/www/app_module.ts b/scouting/www/app_module.ts
index 3e34a17..6a6fff0 100644
--- a/scouting/www/app_module.ts
+++ b/scouting/www/app_module.ts
@@ -1,6 +1,7 @@
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
+import {EntryModule} from './entry/entry.module';
import {App} from './app';
@@ -9,6 +10,7 @@
imports: [
BrowserModule,
BrowserAnimationsModule,
+ EntryModule,
],
exports: [App],
bootstrap: [App],
diff --git a/scouting/www/entry/BUILD b/scouting/www/entry/BUILD
new file mode 100644
index 0000000..55b6937
--- /dev/null
+++ b/scouting/www/entry/BUILD
@@ -0,0 +1,25 @@
+load("@npm//@bazel/typescript:index.bzl", "ts_library")
+
+ts_library(
+ name = "entry",
+ srcs = glob([
+ "*.ts",
+ ]),
+ angular_assets = glob([
+ "*.ng.html",
+ "*.css",
+ ]),
+ compiler = "//tools:tsc_wrapped_with_angular",
+ target_compatible_with = ["@platforms//cpu:x86_64"],
+ use_angular_plugin = True,
+ visibility = ["//visibility:public"],
+ deps = [
+ "//scouting/webserver/requests/messages:error_response_ts_fbs",
+ "//scouting/webserver/requests/messages:submit_data_scouting_response_ts_fbs",
+ "//scouting/webserver/requests/messages:submit_data_scouting_ts_fbs",
+ "@com_github_google_flatbuffers//ts:flatbuffers_ts",
+ "@npm//@angular/common",
+ "@npm//@angular/core",
+ "@npm//@angular/forms",
+ ],
+)
diff --git a/scouting/www/entry/entry.component.css b/scouting/www/entry/entry.component.css
new file mode 100644
index 0000000..2cb500f
--- /dev/null
+++ b/scouting/www/entry/entry.component.css
@@ -0,0 +1,24 @@
+* {
+ padding: 10px;
+}
+
+.center-column {
+ display: flex;
+ align-items: stretch;
+ flex-direction: column;
+ text-align: center;
+}
+
+.buttons {
+ display: flex;
+ justify-content: space-between;
+}
+
+textarea {
+ width: 300px;
+ height: 150px;
+}
+
+.error_message {
+ color: red;
+}
diff --git a/scouting/www/entry/entry.component.ts b/scouting/www/entry/entry.component.ts
new file mode 100644
index 0000000..ddc31df
--- /dev/null
+++ b/scouting/www/entry/entry.component.ts
@@ -0,0 +1,161 @@
+import { Component, OnInit } from '@angular/core';
+
+import * as flatbuffer_builder from 'org_frc971/external/com_github_google_flatbuffers/ts/builder';
+import {ByteBuffer} from 'org_frc971/external/com_github_google_flatbuffers/ts/byte-buffer';
+import * as error_response from 'org_frc971/scouting/webserver/requests/messages/error_response_generated';
+import * as submit_data_scouting_response from 'org_frc971/scouting/webserver/requests/messages/submit_data_scouting_response_generated';
+import * as submit_data_scouting from 'org_frc971/scouting/webserver/requests/messages/submit_data_scouting_generated';
+import SubmitDataScouting = submit_data_scouting.scouting.webserver.requests.SubmitDataScouting;
+import SubmitDataScoutingResponse = submit_data_scouting_response.scouting.webserver.requests.SubmitDataScoutingResponse;
+import ErrorResponse = error_response.scouting.webserver.requests.ErrorResponse;
+
+type Section = 'Team Selection'|'Auto'|'TeleOp'|'Climb'|'Defense'|'Review and Submit'|'Home'
+type Level = 'Low'|'Medium'|'High'|'Transversal'
+
+@Component({
+ selector: 'app-entry',
+ templateUrl: './entry.ng.html',
+ styleUrls: ['./entry.component.css']
+})
+export class EntryComponent {
+ section: Section = 'Team Selection';
+ matchNumber: number = 1
+ teamNumber: number = 1
+ autoUpperShotsMade: number = 0;
+ autoLowerShotsMade: number = 0;
+ autoShotsMissed: number = 0;
+ teleUpperShotsMade: number = 0;
+ teleLowerShotsMade: number = 0;
+ teleShotsMissed: number = 0;
+ defensePlayedOnScore: number = 3;
+ defensePlayedScore: number = 3;
+ level: Level;
+ proper: boolean = false;
+ climbed: boolean = false;
+ errorMessage: string = '';
+
+ toggleProper() {
+ this.proper = !this.proper;
+ }
+
+ setLow() {
+ this.level = 'Low';
+ }
+
+ setMedium() {
+ this.level = 'Medium';
+ }
+
+ setHigh() {
+ this.level = 'High';
+ }
+
+ setTransversal() {
+ this.level = 'Transversal';
+ }
+
+ defensePlayedOnSlider(event) {
+ this.defensePlayedOnScore = event.target.value;
+ }
+
+ defensePlayedSlider(event) {
+ this.defensePlayedScore = event.target.value;
+ }
+
+ setClimbedTrue() {
+ this.climbed = true;
+ }
+
+ setClimbedFalse() {
+ this.climbed = false;
+ }
+
+ nextSection() {
+ if (this.section === 'Team Selection') {
+ this.section = 'Auto';
+ } else if (this.section === 'Auto') {
+ this.section = 'TeleOp';
+ } else if (this.section === 'TeleOp') {
+ this.section = 'Climb';
+ } else if (this.section === 'Climb') {
+ this.section = 'Defense';
+ } else if (this.section === 'Defense') {
+ this.section = 'Review and Submit';
+ } else if (this.section === 'Review and Submit') {
+ this.submitDataScouting();
+ }
+ }
+
+ prevSection() {
+ if (this.section === 'Auto') {
+ this.section = 'Team Selection';
+ } else if (this.section === 'TeleOp') {
+ this.section = 'Auto';
+ } else if (this.section === 'Climb') {
+ this.section = 'TeleOp';
+ } else if (this.section === 'Defense') {
+ this.section = 'Climb';
+ } else if (this.section === 'Review and Submit') {
+ this.section = 'Defense';
+ }
+ }
+
+ adjustAutoUpper(by: number) {
+ this.autoUpperShotsMade = Math.max(0, this.autoUpperShotsMade + by);
+ }
+
+ adjustAutoLower(by: number) {
+ this.autoLowerShotsMade = Math.max(0, this.autoLowerShotsMade + by);
+ }
+
+ adjustAutoMissed(by: number) {
+ this.autoShotsMissed = Math.max(0, this.autoShotsMissed + by);
+ }
+
+ adjustTeleUpper(by: number) {
+ this.teleUpperShotsMade = Math.max(0, this.teleUpperShotsMade + by);
+ }
+
+ adjustTeleLower(by: number) {
+ this.teleLowerShotsMade = Math.max(0, this.teleLowerShotsMade + by);
+ }
+
+ adjustTeleMissed(by: number) {
+ this.teleShotsMissed = Math.max(0, this.teleShotsMissed + by);
+ }
+
+ async submitDataScouting() {
+ const builder = new flatbuffer_builder.Builder() as unknown as flatbuffers.Builder;
+ SubmitDataScouting.startSubmitDataScouting(builder);
+ SubmitDataScouting.addTeam(builder, this.teamNumber);
+ SubmitDataScouting.addMatch(builder, this.matchNumber);
+ SubmitDataScouting.addMissedShotsAuto(builder, this.autoShotsMissed);
+ SubmitDataScouting.addUpperGoalAuto(builder, this.autoUpperShotsMade);
+ SubmitDataScouting.addLowerGoalAuto(builder, this.autoLowerShotsMade);
+ SubmitDataScouting.addMissedShotsTele(builder, this.teleShotsMissed);
+ SubmitDataScouting.addUpperGoalTele(builder, this.teleUpperShotsMade);
+ SubmitDataScouting.addLowerGoalTele(builder, this.teleLowerShotsMade);
+ SubmitDataScouting.addDefenseRating(builder, this.defensePlayedScore);
+ // TODO(phil): Add support for defensePlayedOnScore.
+ // TODO(phil): Fix the Climbing score.
+ SubmitDataScouting.addClimbing(builder, 1);
+ builder.finish(SubmitDataScouting.endSubmitDataScouting(builder));
+
+ const buffer = builder.asUint8Array();
+ const res = await fetch(
+ '/requests/submit/data_scouting', {method: 'POST', body: buffer});
+
+ if (res.ok) {
+ // We successfully submitted the data. Go back to Home.
+ this.section = 'Home';
+ } else {
+ const resBuffer = await res.arrayBuffer();
+ const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
+ const parsedResponse = ErrorResponse.getRootAsErrorResponse(
+ fbBuffer as unknown as flatbuffers.ByteBuffer);
+
+ const errorMessage = parsedResponse.errorMessage();
+ this.errorMessage = `Received ${res.status} ${res.statusText}: "${errorMessage}"`;
+ }
+ }
+}
diff --git a/scouting/www/entry/entry.module.ts b/scouting/www/entry/entry.module.ts
new file mode 100644
index 0000000..35ecd26
--- /dev/null
+++ b/scouting/www/entry/entry.module.ts
@@ -0,0 +1,12 @@
+import {NgModule} from '@angular/core';
+import {CommonModule} from '@angular/common';
+import {EntryComponent} from './entry.component';
+import {FormsModule} from '@angular/forms';
+
+@NgModule({
+ declarations: [EntryComponent],
+ exports: [EntryComponent],
+ imports: [CommonModule, FormsModule],
+})
+export class EntryModule {
+}
diff --git a/scouting/www/entry/entry.ng.html b/scouting/www/entry/entry.ng.html
new file mode 100644
index 0000000..e52e6bc
--- /dev/null
+++ b/scouting/www/entry/entry.ng.html
@@ -0,0 +1,219 @@
+<div class="header">
+ <h2>{{section}}</h2>
+</div>
+
+<ng-container [ngSwitch]="section">
+ <div *ngSwitchCase="'Team Selection'" id="team_selection" class="container-fluid">
+ <div class="row">
+ <label for="match_number">Match Number</label>
+ <input [(ngModel)]="matchNumber" type="number" id="match_number" min="1" max="999">
+ </div>
+ <div class="row">
+ <label for="team_number">Team Number</label>
+ <input [(ngModel)]="teamNumber" type="number" id="team_number" min="1" max="9999">
+ </div>
+ <div class="text-right">
+ <button class="btn btn-primary" (click)="nextSection()">Next</button>
+ </div>
+ </div>
+
+ <div *ngSwitchCase="'Auto'" id="auto" class="container-fluid">
+ <div class="row">
+ <!--Image here-->
+ <h4>Image</h4>
+ <form>
+ <!--Choice for each ball location-->
+ <input type="radio" name="balls" value="1" id="ball-1"><label for="ball-1">Ball 1</label>
+ <input type="radio" name="balls" value="2" id="ball-2"><label for="ball-2">Ball 2</label><br>
+ <input type="radio" name="balls" value="3" id="ball-3"><label for="ball-3">Ball 3</label>
+ <input type="radio" name="balls" value="4" id="ball-4"><label for="ball-4">Ball 4</label>
+ </form>
+ </div>
+ <div class="row">
+ <!--Image here-->
+ <h4>Image</h4>
+ <form>
+ <input type="radio" name="quadrant" id="first" value="Quadrant 1">
+ <label for="first">Quadrant 1</label>
+ <input type="radio" name="quadrant" id="second" value="Quadrant 2">
+ <label for="second">Quadrant 2</label><br>
+ <input type="radio" name="quadrant" id="third" value="Quadrant 3">
+ <label for="third">Quadrant 3</label>
+ <input type="radio" name="quadrant" id="fourth" value="Quadrant 4">
+ <label for="fourth">Quadrant 4</label>
+ </form>
+ </div>
+ <div class="row justify-content-center">
+ <span class="col-4 center-column">
+ <h4>Upper</h4>
+ <button (click)="adjustAutoUpper(1)" class="btn btn-secondary btn-block">+</button>
+ <h3>{{autoUpperShotsMade}}</h3>
+ <button (click)="adjustAutoUpper(-1)" class="btn btn-secondary btn-block">-</button>
+ </span>
+
+ <span class="col-4 center-column">
+ <h4>Lower</h4>
+ <button (click)="adjustAutoLower(1)" class="btn btn-secondary btn-block">+</button>
+ <h3>{{autoLowerShotsMade}}</h3>
+ <button (click)="adjustAutoLower(-1)" class="btn btn-secondary btn-block">-</button>
+ </span>
+
+ <span class="col-4 center-column">
+ <h4>Missed</h4>
+ <button (click)="adjustAutoMissed(1)" class="btn btn-secondary btn-block">+</button>
+ <h3>{{autoShotsMissed}}</h3>
+ <button (click)="adjustAutoMissed(-1)" class="btn btn-secondary btn-block">-</button>
+ </span>
+ </div>
+ <div class="buttons">
+ <!-- hack to right align the next button -->
+ <div></div>
+ <button class="btn btn-primary" (click)="nextSection()">Next</button>
+ </div>
+ </div>
+
+ <div *ngSwitchCase="'TeleOp'" id="teleop" class="container-fluid">
+ <div class="row justify-content-center">
+ <span class="col-4 center-column">
+ <h4>Upper</h4>
+ <button (click)="adjustTeleUpper(1)" class="btn btn-secondary btn-block">+</button>
+ <h3>{{teleUpperShotsMade}}</h3>
+ <button (click)="adjustTeleUpper(-1)" class="btn btn-secondary btn-block">-</button>
+ </span>
+
+ <span class="col-4 center-column">
+ <h4>Lower</h4>
+ <button (click)="adjustTeleLower(1)" class="btn btn-secondary btn-block">+</button>
+ <h3>{{teleLowerShotsMade}}</h3>
+ <button (click)="adjustTeleLower(-1)" class="btn btn-secondary btn-block">-</button>
+ </span>
+
+ <span class="col-4 center-column">
+ <h4>Missed</h4>
+ <button (click)="adjustTeleMissed(1)" class="btn btn-secondary btn-block">+</button>
+ <h3>{{teleShotsMissed}}</h3>
+ <button (click)="adjustTeleMissed(-1)" class="btn btn-secondary btn-block">-</button>
+ </span>
+ </div>
+ <div class="buttons">
+ <button class="btn btn-primary" (click)="prevSection()">Back</button>
+ <button class="btn btn-primary" (click)="nextSection()">Next</button>
+ </div>
+ </div>
+
+ <div *ngSwitchCase="'Climb'" id="climb" class="container-fluid">
+ <div class="row">
+ <form>
+ <input (click)="setClimbedFalse()" type="radio" name="climbing" id="continue"><label for="continue">Kept Shooting</label><br>
+ <input (click)="setClimbedTrue()" type="radio" name="climbing" id="climbed"><label for="climbed">Attempted to Climb</label><br>
+ </form>
+ </div>
+ <div *ngIf="climbed">
+ <h4>Bar Made</h4>
+ <form>
+ <input (click)="setLow()" type="radio" name="level" id="low"><label for="low">Low</label><br>
+ <input (click)="setMedium()" type="radio" name="level" id="medium"><label for="medium">Medium</label><br>
+ <input (click)="setHigh()" type="radio" name="level" id="high"><label for="high">High</label><br>
+ <input (click)="setTransversal()" type="radio" name="level" id="transversal"><label for="transversal">Transversal</label><br>
+ <input (click)="toggleProper()" type="checkbox" id="proper"><label for="proper">~10 seconds to attempt next level?</label>
+ </form>
+ </div>
+ <div class="row">
+ <h4>Comments</h4>
+ <textarea></textarea>
+ </div>
+ <div class="buttons">
+ <button class="btn btn-primary" (click)="prevSection()">Back</button>
+ <button class="btn btn-primary" (click)="nextSection()">Next</button>
+ </div>
+ </div>
+
+ <div *ngSwitchCase="'Defense'" id="defense" class="container-fluid">
+ <h4 class="text-center">How much defense did other robots play on this robot?</h4>
+
+ <div class="row" style="min-height: 50px">
+ <div class="col">
+ <h6>None</h6>
+ </div>
+
+ <div class="col">
+ <input type="range" min="1" max="5" value="3" (input)="defensePlayedOnSlider($event)">
+ </div>
+
+ <div class="col">
+ <h6>A lot</h6>
+ </div>
+ </div>
+
+ <h6 class="text-center">{{defensePlayedOnScore}}</h6>
+
+ <h4 class="text-center">How much defense did this robot play?</h4>
+
+ <div class="row">
+
+ <div class="col">
+ <h6>None</h6>
+ </div>
+
+ <div class="col">
+ <input type="range" min="1" max="5" value="3" (input)="defensePlayedSlider($event)">
+ </div>
+
+ <div class="col">
+ <h6>A lot</h6>
+ </div>
+ </div>
+ <h6 class="text-center">{{defensePlayedScore}}</h6>
+
+ <div class="buttons">
+ <button class="btn btn-primary" (click)="prevSection()">Back</button>
+ <button class="btn btn-primary" (click)="nextSection()">Next</button>
+ </div>
+ </div>
+
+ <div *ngSwitchCase="'Review and Submit'" id="review" class="container-fluid">
+ <h4>Team Selection</h4>
+ <ul>
+ <li>Match number: {{matchNumber}}</li>
+ <li>Team number: {{teamNumber}}</li>
+ </ul>
+
+ <h4>Auto</h4>
+ <ul>
+ <li>Upper Shots Made: {{autoUpperShotsMade}}</li>
+ <li>Lower Shots Made: {{autoLowerShotsMade}}</li>
+ <li>Missed Shots: {{autoShotsMissed}}</li>
+ </ul>
+
+ <h4>TeleOp</h4>
+ <ul>
+ <li>Upper Shots Made: {{teleUpperShotsMade}}</li>
+ <li>Lower Shots Made: {{teleLowerShotsMade}}</li>
+ <li>Missed Shots {{teleShotsMissed}}</li>
+ </ul>
+
+ <h4>Climb</h4>
+ <ul>
+ <div *ngIf="climbed">
+ <li *ngIf="climbed">Attempted to Climb?: Yes</li>
+ <li>Level: {{level}}</li>
+ <li *ngIf="proper">Proper Attempt: Yes</li>
+ <li *ngIf="!proper">Proper Attempt: No</li>
+ </div>
+ <li *ngIf="!climbed">Attempted to Climb: No</li>
+ </ul>
+
+ <h4>Defense</h4>
+ <ul>
+ <li>Defense Played On Rating: {{defensePlayedOnScore}}</li>
+ <li>Defense Played Raing: {{defensePlayedScore}}</li>
+ </ul>
+
+ <div class="error_message">{{ errorMessage }}</div>
+
+ <div class="buttons">
+ <button class="btn btn-primary" (click)="prevSection()">Back</button>
+ <button class="btn btn-primary" (click)="nextSection()">Submit</button>
+ </div>
+ </div>
+</ng-container>
diff --git a/scouting/www/index.html b/scouting/www/index.html
index cbe8770..3a09dfd 100644
--- a/scouting/www/index.html
+++ b/scouting/www/index.html
@@ -1,7 +1,10 @@
+<!DOCTYPE html>
<html>
<head>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
<base href="/">
<script src="./npm/node_modules/zone.js/dist/zone.min.js"></script>
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
</head>
<body>
<my-app></my-app>
diff --git a/tools/build_rules/js.bzl b/tools/build_rules/js.bzl
index be6826c..eeb5594 100644
--- a/tools/build_rules/js.bzl
+++ b/tools/build_rules/js.bzl
@@ -1,6 +1,9 @@
load("@build_bazel_rules_nodejs//:providers.bzl", "JSModuleInfo")
load("@npm//@bazel/rollup:index.bzl", upstream_rollup_bundle = "rollup_bundle")
load("@npm//@bazel/terser:index.bzl", "terser_minified")
+load("@bazel_skylib//lib:paths.bzl", "paths")
+load("@npm//@bazel/protractor:index.bzl", "protractor_web_test_suite")
+load("@npm//@bazel/typescript:index.bzl", "ts_project")
def rollup_bundle(name, deps, visibility = None, **kwargs):
"""Calls the upstream rollup_bundle() and exposes a .min.js file.
@@ -78,3 +81,36 @@
),
},
)
+
+def protractor_ts_test(name, srcs, deps = None, **kwargs):
+ """Wraps upstream protractor_web_test_suite() to reduce boilerplate.
+
+ This is largely based on the upstream protractor example:
+ https://github.com/bazelbuild/rules_nodejs/blob/stable/examples/angular/e2e/BUILD.bazel
+
+ See the documentation for more information:
+ https://bazelbuild.github.io/rules_nodejs/Protractor.html#protractor_web_test_suite
+ """
+ ts_project(
+ name = name + "__lib",
+ srcs = srcs,
+ testonly = 1,
+ deps = (deps or []) + [
+ # Implicit deps that are necessary to get tests of this kind to
+ # work.
+ "@npm//@types/jasmine",
+ "@npm//jasmine",
+ "@npm//protractor",
+ "@npm//@types/node",
+ ],
+ tsconfig = {},
+ declaration = True,
+ declaration_map = True,
+ )
+
+ protractor_web_test_suite(
+ name = name,
+ srcs = [paths.replace_extension(src, ".js") for src in srcs],
+ deps = [":%s__lib" % name],
+ **kwargs
+ )
diff --git a/y2020/control_loops/superstructure/finisher_plotter.ts b/y2020/control_loops/superstructure/finisher_plotter.ts
index 474c8a4..f2127f5 100644
--- a/y2020/control_loops/superstructure/finisher_plotter.ts
+++ b/y2020/control_loops/superstructure/finisher_plotter.ts
@@ -39,7 +39,6 @@
ballsShotPlot.plot.setDefaultYRange([0.0, 20.0]);
ballsShotPlot.addMessageLine(status, ['shooter', 'balls_shot']).setColor(BLUE).setPointSize(0.0);
-
const voltagePlot =
aosPlotter.addPlot(element, [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
voltagePlot.plot.getAxisLabels().setTitle('Voltage');
@@ -51,7 +50,6 @@
voltagePlot.addMessageLine(status, ['shooter', 'finisher', 'voltage_error']).setColor(RED).setPointSize(0.0);
voltagePlot.addMessageLine(robotState, ['voltage_battery']).setColor(GREEN).setPointSize(0.0);
-
const currentPlot =
aosPlotter.addPlot(element, [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
currentPlot.plot.getAxisLabels().setTitle('Current');
diff --git a/y2022/BUILD b/y2022/BUILD
index cc3aa93..1a5f692 100644
--- a/y2022/BUILD
+++ b/y2022/BUILD
@@ -1,9 +1,11 @@
load("//frc971:downloader.bzl", "robot_downloader")
load("//aos:config.bzl", "aos_config")
+load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
load("//tools/build_rules:template.bzl", "jinja2_template")
robot_downloader(
binaries = [
+ ":setpoint_setter",
"//aos/network:web_proxy_main",
],
data = [
@@ -114,6 +116,7 @@
"//aos/network:remote_message_fbs",
"//y2022/localizer:localizer_status_fbs",
"//y2022/localizer:localizer_output_fbs",
+ "//y2022/localizer:localizer_visualization_fbs",
],
target_compatible_with = ["@platforms//os:linux"],
visibility = ["//visibility:public"],
@@ -147,6 +150,7 @@
name = "config_roborio",
src = "y2022_roborio.json",
flatbuffers = [
+ ":setpoint_fbs",
"//aos/network:remote_message_fbs",
"//aos/network:message_bridge_client_fbs",
"//aos/network:message_bridge_server_fbs",
@@ -252,6 +256,8 @@
":joystick_reader.cc",
],
deps = [
+ ":constants",
+ ":setpoint_fbs",
"//aos:init",
"//aos/actions:action_lib",
"//aos/logging",
@@ -267,6 +273,27 @@
],
)
+flatbuffer_cc_library(
+ name = "setpoint_fbs",
+ srcs = [
+ "setpoint.fbs",
+ ],
+ gen_reflections = 1,
+ target_compatible_with = ["@platforms//os:linux"],
+)
+
+cc_binary(
+ name = "setpoint_setter",
+ srcs = ["setpoint_setter.cc"],
+ target_compatible_with = ["@platforms//os:linux"],
+ deps = [
+ ":constants",
+ ":setpoint_fbs",
+ "//aos:init",
+ "//aos/events:shm_event_loop",
+ ],
+)
+
py_library(
name = "python_init",
srcs = ["__init__.py"],
diff --git a/y2022/constants.cc b/y2022/constants.cc
index 1ec0349..225ed87 100644
--- a/y2022/constants.cc
+++ b/y2022/constants.cc
@@ -101,8 +101,8 @@
flipper_arms.subsystem_params.default_profile_params = {6.0, 1.0};
flipper_arms.subsystem_params.range = Values::kFlipperArmRange();
- auto *const flipper_arm_right = &r.flipper_arm_left;
- auto *const flipper_arm_left = &r.flipper_arm_right;
+ auto *const flipper_arm_right = &r.flipper_arm_right;
+ auto *const flipper_arm_left = &r.flipper_arm_left;
*flipper_arm_right = flipper_arms;
*flipper_arm_left = flipper_arms;
@@ -152,20 +152,25 @@
case kCompTeamNumber:
climber->potentiometer_offset = 0.0;
- intake_front->potentiometer_offset = 0.0;
- intake_front->subsystem_params.zeroing_constants
- .measured_absolute_position = 0.0;
- intake_back->potentiometer_offset = 0.0;
- intake_back->subsystem_params.zeroing_constants
- .measured_absolute_position = 0.0;
- turret->potentiometer_offset = 0.0;
- turret->subsystem_params.zeroing_constants.measured_absolute_position =
- 0.0;
- flipper_arm_left->potentiometer_offset = 0.0;
- flipper_arm_right->potentiometer_offset = 0.0;
- catapult_params->zeroing_constants.measured_absolute_position = 0.0;
- catapult->potentiometer_offset = 0.0;
+ intake_front->potentiometer_offset = 2.79628370453323;
+ intake_front->subsystem_params.zeroing_constants
+ .measured_absolute_position = 0.248921954833972;
+
+ intake_back->potentiometer_offset = 3.1409576474047;
+ intake_back->subsystem_params.zeroing_constants
+ .measured_absolute_position = 0.280099007470002;
+
+ turret->potentiometer_offset = -9.99970387166721;
+ turret->subsystem_params.zeroing_constants.measured_absolute_position =
+ 0.638321248163561;
+
+ flipper_arm_left->potentiometer_offset = -6.4;
+ flipper_arm_right->potentiometer_offset = -5.66;
+
+ catapult_params->zeroing_constants.measured_absolute_position =
+ 1.71723370408082;
+ catapult->potentiometer_offset = -2.03383240293769;
break;
case kPracticeTeamNumber:
diff --git a/y2022/constants.h b/y2022/constants.h
index fc9083a..5b8fe64 100644
--- a/y2022/constants.h
+++ b/y2022/constants.h
@@ -48,6 +48,9 @@
return 22 * 0.25 * 0.0254;
}
static constexpr double kClimberPotRatio() { return 1.0; }
+ // TODO(milind): figure this out
+ // Climber position when it's comfortably above the mid rung.
+ static constexpr double kClimberMidRungHeight() { return 1.0; }
struct PotConstants {
::frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemParams<
@@ -63,7 +66,7 @@
static constexpr double kIntakeEncoderCountsPerRevolution() { return 4096.0; }
static constexpr double kIntakeEncoderRatio() {
- return (16.0 / 64.0) * (20.0 / 50.0);
+ return (16.0 / 64.0) * (18.0 / 62.0);
}
static constexpr double kIntakePotRatio() { return 16.0 / 64.0; }
@@ -87,31 +90,57 @@
// TODO (Yash): Constants need to be tuned
static constexpr ::frc971::constants::Range kIntakeRange() {
return ::frc971::constants::Range{
- .lower_hard = -0.5, // Back Hard
- .upper_hard = 2.85 + 0.05, // Front Hard
- .lower = -0.300, // Back Soft
- .upper = 2.725 // Front Soft
+ .lower_hard = -0.85, // Back Hard
+ .upper_hard = 1.85, // Front Hard
+ .lower = -0.400, // Back Soft
+ .upper = 1.57 // Front Soft
};
}
+ // When the intake is atleast this much out, always spin the rollers
+ static constexpr double kIntakeSlightlyOutPosition() {
+ return kIntakeRange().middle();
+ }
+ static constexpr double kIntakeOutPosition() { return 1.24; }
+
// Intake rollers
static constexpr double kIntakeRollerSupplyCurrentLimit() { return 40.0; }
static constexpr double kIntakeRollerStatorCurrentLimit() { return 60.0; }
+ // Transfer rollers
+ // Positive voltage means front transfer rollers pull in and back spits out,
+ // and vice versa
+ static constexpr double kTransferRollerFrontVoltage() { return 12.0; }
+ static constexpr double kTransferRollerBackVoltage() {
+ return -kTransferRollerFrontVoltage();
+ }
+
+ // Voltage to wiggle the transfer rollers and keep a ball in.
+ static constexpr double kTransferRollerFrontWiggleVoltage() { return 5.0; }
+ static constexpr double kTransferRollerBackWiggleVoltage() {
+ return -kTransferRollerFrontWiggleVoltage();
+ }
+ // Minimum roller speed when the intake is slightly out
+ static constexpr double kMinIntakeSlightlyOutRollerSpeed() { return 6.0; }
+ // Roller speeds when intake is out
+ static constexpr double kIntakeOutRollerSpeed() { return 7.0; }
+
// Turret
PotAndAbsEncoderConstants turret;
// TODO (Yash): Constants need to be tuned
static constexpr ::frc971::constants::Range kTurretRange() {
return ::frc971::constants::Range{
- .lower_hard = -0.1, // Back Hard
- .upper_hard = 4.71, // Front Hard
- .lower = 0.0, // Back Soft
- .upper = 3.3 // Front Soft
+ .lower_hard = -6.0, // Back Hard
+ .upper_hard = 4.0, // Front Hard
+ .lower = -5.0, // Back Soft
+ .upper = 3.7 // Front Soft
};
}
- // Turret
+ static constexpr double kTurretBackIntakePos() { return 0.0; }
+ static constexpr double kTurretFrontIntakePos() { return M_PI; }
+
static constexpr double kTurretPotRatio() { return 27.0 / 110.0; }
static constexpr double kTurretEncoderRatio() { return kTurretPotRatio(); }
static constexpr double kTurretEncoderCountsPerRevolution() { return 4096.0; }
@@ -126,11 +155,44 @@
static constexpr double kFlipperArmSupplyCurrentLimit() { return 30.0; }
static constexpr double kFlipperArmStatorCurrentLimit() { return 40.0; }
+ // Voltage to open the flippers for firing
+ static constexpr double kFlipperOpenVoltage() { return 3.0; }
+ // Voltage to keep the flippers open for firing once they already are
+ static constexpr double kFlipperHoldVoltage() { return 2.5; }
+ // Voltage to feed a ball from the transfer rollers to the catpult with the
+ // flippers
+ static constexpr double kFlipperFeedVoltage() { return -8.0; }
+
+ // Ball is fed into catapult for atleast this time no matter what
+ static constexpr std::chrono::milliseconds kExtraLoadingTime() {
+ return std::chrono::milliseconds(100);
+ }
+ // If we have been trying to transfer the ball for this amount of time, it
+ // probably got lost so abort
+ static constexpr std::chrono::seconds kBallLostTime() {
+ return std::chrono::seconds(2);
+ }
+ // If the flippers took more than this amount of time to open for firing,
+ // reseat the ball
+ static constexpr std::chrono::milliseconds kFlipperOpeningTimeout() {
+ return std::chrono::milliseconds(250);
+ }
+ // Don't use flipper velocity readings more than this amount of time in the
+ // past
+ static constexpr std::chrono::milliseconds kFlipperVelocityValidTime() {
+ return std::chrono::milliseconds(100);
+ }
+
// TODO: (Griffin) this needs to be set
static constexpr ::frc971::constants::Range kFlipperArmRange() {
return ::frc971::constants::Range{
- .lower_hard = -0.01, .upper_hard = 0.6, .lower = 0.0, .upper = 0.5};
+ .lower_hard = -0.01, .upper_hard = 0.4, .lower = 0.0, .upper = 0.5};
}
+ // Position of the flippers when they are open
+ static constexpr double kFlipperOpenPosition() { return 0.15; }
+ // If the flippers were open but now moved back, reseat the ball if they go
+ // below this position
+ static constexpr double kReseatFlipperPosition() { return 0.1; }
static constexpr double kFlipperArmsPotRatio() { return 16.0 / 36.0; }
@@ -145,6 +207,9 @@
static constexpr double kCatapultEncoderCountsPerRevolution() {
return 4096.0;
}
+ static constexpr double kDefaultCatapultShotPosition() { return 3.0; }
+ static constexpr double kDefaultCatapultShotVelocity() { return 3.0; }
+ static constexpr double kCatapultReturnPosition() { return -0.85; }
static constexpr double kMaxCatapultEncoderPulsesPerSecond() {
return control_loops::superstructure::catapult::kFreeSpeed / (2.0 * M_PI) *
diff --git a/y2022/control_loops/superstructure/BUILD b/y2022/control_loops/superstructure/BUILD
index ac91668..14fd403 100644
--- a/y2022/control_loops/superstructure/BUILD
+++ b/y2022/control_loops/superstructure/BUILD
@@ -77,6 +77,7 @@
],
deps = [
":collision_avoidance_lib",
+ ":superstructure_can_position_fbs",
":superstructure_goal_fbs",
":superstructure_output_fbs",
":superstructure_position_fbs",
@@ -177,3 +178,36 @@
"//aos/network/www:proxy",
],
)
+
+ts_library(
+ name = "intake_plotter",
+ srcs = ["intake_plotter.ts"],
+ target_compatible_with = ["@platforms//os:linux"],
+ deps = [
+ "//aos/network/www:aos_plotter",
+ "//aos/network/www:colors",
+ "//aos/network/www:proxy",
+ ],
+)
+
+ts_library(
+ name = "turret_plotter",
+ srcs = ["turret_plotter.ts"],
+ target_compatible_with = ["@platforms//os:linux"],
+ deps = [
+ "//aos/network/www:aos_plotter",
+ "//aos/network/www:colors",
+ "//aos/network/www:proxy",
+ ],
+)
+
+ts_library(
+ name = "climber_plotter",
+ srcs = ["climber_plotter.ts"],
+ target_compatible_with = ["@platforms//os:linux"],
+ deps = [
+ "//aos/network/www:aos_plotter",
+ "//aos/network/www:colors",
+ "//aos/network/www:proxy",
+ ],
+)
diff --git a/y2022/control_loops/superstructure/catapult/catapult.cc b/y2022/control_loops/superstructure/catapult/catapult.cc
index e4d76d3..adc13c7 100644
--- a/y2022/control_loops/superstructure/catapult/catapult.cc
+++ b/y2022/control_loops/superstructure/catapult/catapult.cc
@@ -23,7 +23,7 @@
instance.constraint_matrix =
Eigen::SparseMatrix<double, Eigen::ColMajor, osqp::c_int>(horizon,
- horizon);
+ horizon);
instance.constraint_matrix.setIdentity();
instance.lower_bounds =
@@ -313,7 +313,7 @@
const flatbuffers::Offset<
frc971::control_loops::PotAndAbsoluteEncoderProfiledJointStatus>
Catapult::Iterate(const Goal *unsafe_goal, const Position *position,
- double *catapult_voltage,
+ double *catapult_voltage, bool fire,
flatbuffers::FlatBufferBuilder *fbb) {
const frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal
*catapult_goal = unsafe_goal != nullptr && unsafe_goal->has_catapult()
@@ -326,13 +326,12 @@
if (catapult_disabled) {
catapult_state_ = CatapultState::PROFILE;
} else if (catapult_.running() && unsafe_goal &&
- unsafe_goal->has_catapult() && unsafe_goal->catapult()->fire() &&
- !last_firing_) {
+ unsafe_goal->has_catapult() && fire && !last_firing_) {
catapult_state_ = CatapultState::FIRING;
}
if (catapult_.running() && unsafe_goal && unsafe_goal->has_catapult()) {
- last_firing_ = unsafe_goal->catapult()->fire();
+ last_firing_ = fire;
}
use_profile_ = true;
@@ -379,8 +378,7 @@
use_profile_ = false;
}
} else {
- if (unsafe_goal && unsafe_goal->has_catapult() &&
- !unsafe_goal->catapult()->fire()) {
+ if (unsafe_goal && unsafe_goal->has_catapult() && !fire) {
// Eh, didn't manage to solve before it was time to fire. Give up.
catapult_state_ = CatapultState::PROFILE;
}
@@ -417,7 +415,8 @@
}
}
- catapult_.UpdateObserver(catapult_voltage != nullptr ? *catapult_voltage : 0.0);
+ catapult_.UpdateObserver(catapult_voltage != nullptr ? *catapult_voltage
+ : 0.0);
return catapult_.MakeStatus(fbb);
}
diff --git a/y2022/control_loops/superstructure/catapult/catapult.h b/y2022/control_loops/superstructure/catapult/catapult.h
index a8141a0..ccd4b06 100644
--- a/y2022/control_loops/superstructure/catapult/catapult.h
+++ b/y2022/control_loops/superstructure/catapult/catapult.h
@@ -192,6 +192,8 @@
// Resets all state for when WPILib restarts.
void Reset() { catapult_.Reset(); }
+ void Estop() { catapult_.Estop(); }
+
bool zeroed() const { return catapult_.zeroed(); }
bool estopped() const { return catapult_.estopped(); }
double solve_time() const { return catapult_mpc_.solve_time(); }
@@ -201,12 +203,16 @@
// Returns the number of shots taken.
int shot_count() const { return shot_count_; }
+ // Returns the estimated position
+ double estimated_position() const { return catapult_.estimated_position(); }
+
// Runs either the MPC or the profiled subsystem depending on if we are
// shooting or not. Returns the status.
const flatbuffers::Offset<
frc971::control_loops::PotAndAbsoluteEncoderProfiledJointStatus>
Iterate(const Goal *unsafe_goal, const Position *position,
- double *catapult_voltage, flatbuffers::FlatBufferBuilder *fbb);
+ double *catapult_voltage, bool fire,
+ flatbuffers::FlatBufferBuilder *fbb);
private:
// TODO(austin): Prototype is just an encoder. Catapult has both an encoder
diff --git a/y2022/control_loops/superstructure/climber_plotter.ts b/y2022/control_loops/superstructure/climber_plotter.ts
new file mode 100644
index 0000000..e24a993
--- /dev/null
+++ b/y2022/control_loops/superstructure/climber_plotter.ts
@@ -0,0 +1,46 @@
+// Provides a plot for debugging robot state-related issues.
+import {AosPlotter} from 'org_frc971/aos/network/www/aos_plotter';
+import * as proxy from 'org_frc971/aos/network/www/proxy';
+import {BLUE, BROWN, CYAN, GREEN, PINK, RED, WHITE, ORANGE} from 'org_frc971/aos/network/www/colors';
+
+import Connection = proxy.Connection;
+
+const TIME = AosPlotter.TIME;
+const DEFAULT_WIDTH = AosPlotter.DEFAULT_WIDTH * 5 / 2;
+const DEFAULT_HEIGHT = AosPlotter.DEFAULT_HEIGHT * 3;
+
+export function plotClimber(conn: Connection, element: Element) : void {
+ const aosPlotter = new AosPlotter(conn);
+ const goal = aosPlotter.addMessageSource('/superstructure', 'y2022.control_loops.superstructure.Goal');
+ const output = aosPlotter.addMessageSource('/superstructure', 'y2022.control_loops.superstructure.Output');
+ const status = aosPlotter.addMessageSource('/superstructure', 'y2022.control_loops.superstructure.Status');
+ const robotState = aosPlotter.addMessageSource('/aos', 'aos.RobotState');
+
+ // Robot Enabled/Disabled and Mode
+ const positionPlot =
+ aosPlotter.addPlot(element, [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ positionPlot.plot.getAxisLabels().setTitle('Position');
+ positionPlot.plot.getAxisLabels().setXLabel(TIME);
+ positionPlot.plot.getAxisLabels().setYLabel('rad');
+ positionPlot.plot.setDefaultYRange([-1.0, 2.0]);
+
+ positionPlot.addMessageLine(status, ['climber', 'position']).setColor(GREEN).setPointSize(4.0);
+ positionPlot.addMessageLine(status, ['climber', 'velocity']).setColor(PINK).setPointSize(1.0);
+ positionPlot.addMessageLine(status, ['climber', 'goal_position']).setColor(RED).setPointSize(4.0);
+ positionPlot.addMessageLine(status, ['climber', 'goal_velocity']).setColor(ORANGE).setPointSize(4.0);
+ positionPlot.addMessageLine(status, ['climber', 'estimator_state', 'position']).setColor(CYAN).setPointSize(1.0);
+
+ const voltagePlot =
+ aosPlotter.addPlot(element, [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ voltagePlot.plot.getAxisLabels().setTitle('Voltage');
+ voltagePlot.plot.getAxisLabels().setXLabel(TIME);
+ voltagePlot.plot.getAxisLabels().setYLabel('Volts');
+ voltagePlot.plot.setDefaultYRange([-4.0, 14.0]);
+
+ voltagePlot.addMessageLine(output, ['climber_voltage']).setColor(BLUE).setPointSize(4.0);
+ voltagePlot.addMessageLine(status, ['climber', 'voltage_error']).setColor(RED).setPointSize(1.0);
+ voltagePlot.addMessageLine(status, ['climber', 'position_power']).setColor(BROWN).setPointSize(1.0);
+ voltagePlot.addMessageLine(status, ['climber', 'velocity_power']).setColor(CYAN).setPointSize(1.0);
+ voltagePlot.addMessageLine(robotState, ['voltage_battery']).setColor(GREEN).setPointSize(1.0);
+
+}
diff --git a/y2022/control_loops/superstructure/collision_avoidance.cc b/y2022/control_loops/superstructure/collision_avoidance.cc
index 5d0fe27..01b0463 100644
--- a/y2022/control_loops/superstructure/collision_avoidance.cc
+++ b/y2022/control_loops/superstructure/collision_avoidance.cc
@@ -58,7 +58,7 @@
if (turret_position_wrapped >= min_turret_collision_position &&
turret_position_wrapped <= max_turret_collision_position) {
// Reterns true if the intake is raised.
- if (intake_position <= kCollisionZoneIntake) {
+ if (intake_position > kCollisionZoneIntake) {
return true;
}
} else {
@@ -67,8 +67,10 @@
return false;
}
-void CollisionAvoidance::UpdateGoal(const CollisionAvoidance::Status &status,
- const Goal *unsafe_goal) {
+void CollisionAvoidance::UpdateGoal(
+ const CollisionAvoidance::Status &status,
+ const frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal
+ *unsafe_turret_goal) {
// Start with our constraints being wide open.
clear_max_turret_goal();
clear_min_turret_goal();
@@ -81,10 +83,9 @@
const double intake_back_position = status.intake_back_position;
const double turret_position = status.turret_position;
- const double turret_goal =
- (unsafe_goal != nullptr && unsafe_goal->turret() != nullptr
- ? unsafe_goal->turret()->unsafe_goal()
- : std::numeric_limits<double>::quiet_NaN());
+ const double turret_goal = (unsafe_turret_goal != nullptr
+ ? unsafe_turret_goal->unsafe_goal()
+ : std::numeric_limits<double>::quiet_NaN());
// Calculating the avoidance with either intake, and when the turret is
// wrapped.
@@ -143,14 +144,14 @@
if (turret_pos_unsafe || turret_moving_past_intake) {
// If the turret is unsafe, limit the intake
if (intake_front) {
- update_min_intake_front_goal(kCollisionZoneIntake + kEpsIntake);
+ update_max_intake_front_goal(kCollisionZoneIntake - kEpsIntake);
} else {
- update_min_intake_back_goal(kCollisionZoneIntake + kEpsIntake);
+ update_max_intake_back_goal(kCollisionZoneIntake - kEpsIntake);
}
// If the intake is in the way, limit the turret until moved. Otherwise,
// let'errip!
- if (!turret_pos_unsafe && (intake_position <= kCollisionZoneIntake)) {
+ if (!turret_pos_unsafe && (intake_position > kCollisionZoneIntake)) {
if (turret_position < min_turret_collision_goal_unwrapped) {
update_max_turret_goal(min_turret_collision_goal_unwrapped -
kEpsTurret);
diff --git a/y2022/control_loops/superstructure/collision_avoidance.h b/y2022/control_loops/superstructure/collision_avoidance.h
index 94b454c..a64bbd3 100644
--- a/y2022/control_loops/superstructure/collision_avoidance.h
+++ b/y2022/control_loops/superstructure/collision_avoidance.h
@@ -52,8 +52,8 @@
static constexpr double kMinCollisionZoneBackTurret = -kCollisionZoneTurret;
static constexpr double kMaxCollisionZoneBackTurret = kCollisionZoneTurret;
- // Minimum (highest in reality) of the intake, in order to avoid collisions
- static constexpr double kCollisionZoneIntake = M_PI / 6.0;
+ // Maximum position of the intake to avoid collisions
+ static constexpr double kCollisionZoneIntake = 1.4;
// Tolerance for the turret.
static constexpr double kEpsTurret = 0.05;
@@ -69,7 +69,10 @@
double min_turret_collision_position,
double max_turret_collision_position);
// Checks and alters goals to make sure they're safe.
- void UpdateGoal(const Status &status, const Goal *unsafe_goal);
+ void UpdateGoal(
+ const Status &status,
+ const frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal
+ *unsafe_turret_goal);
// Limits if goal is in collision spots.
void CalculateAvoidance(bool intake_front, double intake_position,
double turret_goal, double mix_turret_collision_goal,
diff --git a/y2022/control_loops/superstructure/collision_avoidance_test.cc b/y2022/control_loops/superstructure/collision_avoidance_test.cc
index 616a10b..adf672b 100644
--- a/y2022/control_loops/superstructure/collision_avoidance_test.cc
+++ b/y2022/control_loops/superstructure/collision_avoidance_test.cc
@@ -2,8 +2,8 @@
#include "aos/commonmath.h"
#include "aos/flatbuffers.h"
-#include "gtest/gtest.h"
#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#include "y2022/control_loops/superstructure/superstructure_goal_generated.h"
#include "y2022/control_loops/superstructure/superstructure_status_generated.h"
@@ -84,22 +84,18 @@
status_({0.0, 0.0, 0.0}),
prev_status_({0.0, 0.0, 0.0}) {}
- int t = 0;
- int d = 0;
void Simulate() {
FlatbufferDetachedBuffer<Goal> safe_goal = MakeZeroGoal();
- t++;
// Don't simulate if already collided
if (avoidance_.IsCollided(status_)) {
- d++;
return;
}
bool moving = true;
while (moving) {
// Compute the safe goal
- avoidance_.UpdateGoal(status_, &unsafe_goal_.message());
+ avoidance_.UpdateGoal(status_, unsafe_goal_.message().turret());
// The system should never be collided
ASSERT_FALSE(avoidance_.IsCollided(status_));
@@ -142,11 +138,11 @@
switch (intake_state) {
case IntakeState::kSafe:
- intake_angle = CollisionAvoidance::kCollisionZoneIntake +
+ intake_angle = CollisionAvoidance::kCollisionZoneIntake -
CollisionAvoidance::kEpsIntake;
break;
case IntakeState::kUnsafe:
- intake_angle = CollisionAvoidance::kCollisionZoneIntake -
+ intake_angle = CollisionAvoidance::kCollisionZoneIntake +
CollisionAvoidance::kEpsIntake;
break;
}
@@ -271,7 +267,7 @@
intake_front_goal(), turret_goal(),
CollisionAvoidance::kMinCollisionZoneFrontTurret,
CollisionAvoidance::kMaxCollisionZoneFrontTurret)) {
- EXPECT_GE(status_.intake_front_position,
+ EXPECT_LE(status_.intake_front_position,
CollisionAvoidance::kCollisionZoneIntake);
} else {
EXPECT_NEAR(intake_front_goal(), status_.intake_front_position,
@@ -282,7 +278,7 @@
intake_back_goal(), turret_goal(),
CollisionAvoidance::kMinCollisionZoneBackTurret,
CollisionAvoidance::kMaxCollisionZoneBackTurret)) {
- EXPECT_GE(status_.intake_back_position,
+ EXPECT_LE(status_.intake_back_position,
CollisionAvoidance::kCollisionZoneIntake);
} else {
EXPECT_NEAR(intake_back_goal(), status_.intake_back_position, 0.001);
diff --git a/y2022/control_loops/superstructure/intake_plotter.ts b/y2022/control_loops/superstructure/intake_plotter.ts
new file mode 100644
index 0000000..8904d8b
--- /dev/null
+++ b/y2022/control_loops/superstructure/intake_plotter.ts
@@ -0,0 +1,88 @@
+// Provides a plot for debugging robot state-related issues.
+import {AosPlotter} from 'org_frc971/aos/network/www/aos_plotter';
+import * as proxy from 'org_frc971/aos/network/www/proxy';
+import {BLUE, BROWN, CYAN, GREEN, PINK, RED, WHITE, ORANGE} from 'org_frc971/aos/network/www/colors';
+
+import Connection = proxy.Connection;
+
+const TIME = AosPlotter.TIME;
+const DEFAULT_WIDTH = AosPlotter.DEFAULT_WIDTH * 5 / 2;
+const DEFAULT_HEIGHT = AosPlotter.DEFAULT_HEIGHT * 3;
+
+export function plotIntakeFront(conn: Connection, element: Element) : void {
+ const aosPlotter = new AosPlotter(conn);
+ const goal = aosPlotter.addMessageSource('/superstructure', 'y2022.control_loops.superstructure.Goal');
+ const output = aosPlotter.addMessageSource('/superstructure', 'y2022.control_loops.superstructure.Output');
+ const status = aosPlotter.addMessageSource('/superstructure', 'y2022.control_loops.superstructure.Status');
+ const robotState = aosPlotter.addMessageSource('/aos', 'aos.RobotState');
+
+ // Robot Enabled/Disabled and Mode
+ const positionPlotFront =
+ aosPlotter.addPlot(element, [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ positionPlotFront.plot.getAxisLabels().setTitle('Position');
+ positionPlotFront.plot.getAxisLabels().setXLabel(TIME);
+ positionPlotFront.plot.getAxisLabels().setYLabel('rad');
+ positionPlotFront.plot.setDefaultYRange([-1.0, 2.0]);
+
+ positionPlotFront.addMessageLine(status, ['intake_front', 'position']).setColor(GREEN).setPointSize(4.0);
+ positionPlotFront.addMessageLine(status, ['intake_front', 'velocity']).setColor(PINK).setPointSize(1.0);
+ positionPlotFront.addMessageLine(status, ['intake_front', 'goal_position']).setColor(RED).setPointSize(4.0);
+ positionPlotFront.addMessageLine(status, ['intake_front', 'goal_velocity']).setColor(ORANGE).setPointSize(4.0);
+ positionPlotFront.addMessageLine(status, ['intake_front', 'estimator_state', 'position']).setColor(CYAN).setPointSize(1.0);
+
+ const voltagePlotFront =
+ aosPlotter.addPlot(element, [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ voltagePlotFront.plot.getAxisLabels().setTitle('Voltage');
+ voltagePlotFront.plot.getAxisLabels().setXLabel(TIME);
+ voltagePlotFront.plot.getAxisLabels().setYLabel('Volts');
+ voltagePlotFront.plot.setDefaultYRange([-4.0, 14.0]);
+
+ voltagePlotFront.addMessageLine(output, ['intake_voltage_front']).setColor(BLUE).setPointSize(4.0);
+ voltagePlotFront.addMessageLine(status, ['intake_front', 'voltage_error']).setColor(RED).setPointSize(1.0);
+ voltagePlotFront.addMessageLine(status, ['intake_front', 'position_power']).setColor(BROWN).setPointSize(1.0);
+ voltagePlotFront.addMessageLine(status, ['intake_front', 'velocity_power']).setColor(CYAN).setPointSize(1.0);
+ voltagePlotFront.addMessageLine(robotState, ['voltage_battery']).setColor(GREEN).setPointSize(1.0);
+}
+
+export function plotIntakeBack(conn: Connection, element: Element) : void {
+ const aosPlotter = new AosPlotter(conn);
+ const goal = aosPlotter.addMessageSource('/superstructure', 'y2022.control_loops.superstructure.Goal');
+ const output = aosPlotter.addMessageSource('/superstructure', 'y2022.control_loops.superstructure.Output');
+ const status = aosPlotter.addMessageSource('/superstructure', 'y2022.control_loops.superstructure.Status');
+ const robotState = aosPlotter.addMessageSource('/aos', 'aos.RobotState');
+
+ // Robot Enabled/Disabled and Mode
+ const positionPlotFront =
+ aosPlotter.addPlot(element, [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ positionPlotFront.plot.getAxisLabels().setTitle('Position');
+ positionPlotFront.plot.getAxisLabels().setXLabel(TIME);
+ positionPlotFront.plot.getAxisLabels().setYLabel('rad');
+ positionPlotFront.plot.setDefaultYRange([-1.0, 2.0]);
+
+ const positionPlotBack =
+ aosPlotter.addPlot(element, [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ positionPlotBack.plot.getAxisLabels().setTitle('Position');
+ positionPlotBack.plot.getAxisLabels().setXLabel(TIME);
+ positionPlotBack.plot.getAxisLabels().setYLabel('rad');
+ positionPlotBack.plot.setDefaultYRange([-1.0, 2.0]);
+
+ positionPlotBack.addMessageLine(status, ['intake_back', 'position']).setColor(GREEN).setPointSize(4.0);
+ positionPlotBack.addMessageLine(status, ['intake_back', 'velocity']).setColor(PINK).setPointSize(1.0);
+ positionPlotBack.addMessageLine(status, ['intake_back', 'goal_position']).setColor(RED).setPointSize(4.0);
+ positionPlotBack.addMessageLine(status, ['intake_back', 'goal_velocity']).setColor(ORANGE).setPointSize(4.0);
+ positionPlotBack.addMessageLine(status, ['intake_back', 'estimator_state', 'position']).setColor(CYAN).setPointSize(1.0);
+
+
+ const voltagePlotBack =
+ aosPlotter.addPlot(element, [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ voltagePlotBack.plot.getAxisLabels().setTitle('Voltage');
+ voltagePlotBack.plot.getAxisLabels().setXLabel(TIME);
+ voltagePlotBack.plot.getAxisLabels().setYLabel('Volts');
+ voltagePlotBack.plot.setDefaultYRange([-4.0, 14.0]);
+
+ voltagePlotBack.addMessageLine(output, ['intake_voltage_back']).setColor(BLUE).setPointSize(4.0);
+ voltagePlotBack.addMessageLine(status, ['intake_back', 'voltage_error']).setColor(RED).setPointSize(1.0);
+ voltagePlotBack.addMessageLine(status, ['intake_back', 'position_power']).setColor(BROWN).setPointSize(1.0);
+ voltagePlotBack.addMessageLine(status, ['intake_back', 'velocity_power']).setColor(CYAN).setPointSize(1.0);
+ voltagePlotBack.addMessageLine(robotState, ['voltage_battery']).setColor(GREEN).setPointSize(1.0);
+}
diff --git a/y2022/control_loops/superstructure/superstructure.cc b/y2022/control_loops/superstructure/superstructure.cc
index bf94b08..affc25b 100644
--- a/y2022/control_loops/superstructure/superstructure.cc
+++ b/y2022/control_loops/superstructure/superstructure.cc
@@ -21,10 +21,12 @@
intake_front_(values_->intake_front.subsystem_params),
intake_back_(values_->intake_back.subsystem_params),
turret_(values_->turret.subsystem_params),
+ catapult_(*values_),
drivetrain_status_fetcher_(
event_loop->MakeFetcher<frc971::control_loops::drivetrain::Status>(
"/drivetrain")),
- catapult_(*values_) {
+ can_position_fetcher_(
+ event_loop->MakeFetcher<CANPosition>("/superstructure")) {
event_loop->SetRuntimeRealtimePriority(30);
}
@@ -32,8 +34,6 @@
const Position *position,
aos::Sender<Output>::Builder *output,
aos::Sender<Status>::Builder *status) {
- OutputT output_struct;
-
if (WasReset()) {
AOS_LOG(ERROR, "WPILib reset, restarting\n");
intake_front_.Reset();
@@ -43,27 +43,28 @@
catapult_.Reset();
}
- collision_avoidance_.UpdateGoal(
- {.intake_front_position = intake_front_.estimated_position(),
- .intake_back_position = intake_back_.estimated_position(),
- .turret_position = turret_.estimated_position()},
- unsafe_goal);
+ OutputT output_struct;
- turret_.set_min_position(collision_avoidance_.min_turret_goal());
- turret_.set_max_position(collision_avoidance_.max_turret_goal());
- intake_front_.set_min_position(collision_avoidance_.min_intake_front_goal());
- intake_front_.set_max_position(collision_avoidance_.max_intake_front_goal());
- intake_back_.set_min_position(collision_avoidance_.min_intake_back_goal());
- intake_back_.set_max_position(collision_avoidance_.max_intake_back_goal());
+ aos::FlatbufferFixedAllocatorArray<
+ frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal, 64>
+ turret_goal_buffer;
+
+ const aos::monotonic_clock::time_point timestamp =
+ event_loop()->context().monotonic_event_time;
drivetrain_status_fetcher_.Fetch();
const float velocity = robot_velocity();
- double roller_speed_compensated_front = 0;
- double roller_speed_compensated_back = 0;
- double transfer_roller_speed = 0;
+ const frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal
+ *turret_goal = nullptr;
+ double roller_speed_compensated_front = 0.0;
+ double roller_speed_compensated_back = 0.0;
+ double transfer_roller_speed = 0.0;
+ double flipper_arms_voltage = 0.0;
if (unsafe_goal != nullptr) {
+ turret_goal = unsafe_goal->turret();
+
roller_speed_compensated_front =
unsafe_goal->roller_speed_front() +
std::max(velocity * unsafe_goal->roller_speed_compensation(), 0.0);
@@ -75,45 +76,308 @@
transfer_roller_speed = unsafe_goal->transfer_roller_speed();
}
+ // TODO: Aimer sets turret_goal here
+ // Supersturcture state machine:
+ // 1. IDLE: Wait until an intake beambreak is triggerred, meaning that a ball
+ // is being intaked. This means that the transfer rollers have a ball. If
+ // we've been waiting here for too long without any beambreak triggered, the
+ // ball got lost, so reset.
+ // 2. TRANSFERRING: Until the turret reaches the loading position where the
+ // ball can be transferred into the catapult, wiggle the ball in place.
+ // Once the turret reaches the loading position, send the ball forward with
+ // the transfer rollers until the turret beambreak is triggered.
+ // If we have been in this state for too long, the ball probably got lost so
+ // reset back to IDLE.
+ // 3. LOADING: To load the ball into the catapult, put the flippers at the
+ // feeding speed. Wait for a timeout, and then wait until the ball has gone
+ // past the turret beambreak and the flippers have stopped moving, meaning
+ // that the ball is fully loaded in the catapult.
+ // 4. LOADED: Wait until the user asks us to fire to transition to the
+ // shooting stage. If asked to cancel the shot, reset back to the IDLE state.
+ // 5. SHOOTING: Open the flippers to get ready for the shot. If they don't
+ // open quickly enough, try reseating the ball and going back to the LOADING
+ // stage, which moves the flippers in the opposite direction first.
+ // Now, hold the flippers open and wait until the turret has reached its
+ // aiming goal. Once the turret is ready, tell the catapult to fire.
+ // If the flippers move back for some reason now, it could damage the
+ // catapult, so estop it. Otherwise, wait until the catapult shoots a ball and
+ // goes back to its return position. We have now finished the shot, so return
+ // to IDLE.
+
+ const bool is_spitting = ((intake_state_ == IntakeState::INTAKE_FRONT_BALL &&
+ transfer_roller_speed < 0) ||
+ (intake_state_ == IntakeState::INTAKE_BACK_BALL &&
+ transfer_roller_speed > 0));
+
+ // Intake handling should happen regardless of the turret state
+ if (position->intake_beambreak_front() || position->intake_beambreak_back()) {
+ if (intake_state_ == IntakeState::NO_BALL) {
+ if (position->intake_beambreak_front()) {
+ intake_state_ = IntakeState::INTAKE_FRONT_BALL;
+ } else if (position->intake_beambreak_back()) {
+ intake_state_ = IntakeState::INTAKE_BACK_BALL;
+ }
+ }
+
+ intake_beambreak_timer_ = timestamp;
+ }
+
+ if (intake_state_ != IntakeState::NO_BALL) {
+ // Block intaking in
+ roller_speed_compensated_front = 0.0;
+ roller_speed_compensated_back = 0.0;
+
+ const double wiggle_voltage =
+ (intake_state_ == IntakeState::INTAKE_FRONT_BALL
+ ? constants::Values::kTransferRollerFrontWiggleVoltage()
+ : constants::Values::kTransferRollerBackWiggleVoltage());
+ // Wiggle transfer rollers: send the ball back and forth while waiting
+ // for the turret or waiting for another shot to be completed
+ if ((intake_state_ == IntakeState::INTAKE_FRONT_BALL &&
+ position->intake_beambreak_front()) ||
+ (intake_state_ == IntakeState::INTAKE_BACK_BALL &&
+ position->intake_beambreak_back())) {
+ transfer_roller_speed = -wiggle_voltage;
+ } else {
+ transfer_roller_speed = wiggle_voltage;
+ }
+ }
+
+ switch (state_) {
+ case SuperstructureState::IDLE: {
+ if (timestamp >
+ intake_beambreak_timer_ + constants::Values::kBallLostTime()) {
+ intake_state_ = IntakeState::NO_BALL;
+ }
+
+ if (is_spitting) {
+ intake_state_ = IntakeState::NO_BALL;
+ }
+
+ if (intake_state_ == IntakeState::NO_BALL ||
+ !(position->intake_beambreak_front() ||
+ position->intake_beambreak_back())) {
+ break;
+ }
+
+ state_ = SuperstructureState::TRANSFERRING;
+ transferring_timer_ = timestamp;
+
+ // Save the side the ball is on for later
+
+ break;
+ }
+ case SuperstructureState::TRANSFERRING: {
+ // If we've been transferring for too long, the ball probably got lost
+ if (timestamp >
+ transferring_timer_ + constants::Values::kBallLostTime()) {
+ intake_state_ = IntakeState::NO_BALL;
+ break;
+ }
+
+ if (intake_state_ == IntakeState::NO_BALL) {
+ state_ = SuperstructureState::IDLE;
+ break;
+ }
+
+ double turret_loading_position =
+ (intake_state_ == IntakeState::INTAKE_FRONT_BALL
+ ? constants::Values::kTurretFrontIntakePos()
+ : constants::Values::kTurretBackIntakePos());
+
+ turret_goal_buffer.Finish(
+ frc971::control_loops::
+ CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
+ *turret_goal_buffer.fbb(), turret_loading_position));
+ turret_goal = &turret_goal_buffer.message();
+
+ const bool turret_near_goal =
+ std::abs(turret_.estimated_position() - turret_loading_position) <
+ kTurretGoalThreshold;
+ if (!turret_near_goal) {
+ break; // Wait for turret to reach the chosen intake
+ }
+
+ // Transfer rollers and flipper arm belt on
+ transfer_roller_speed =
+ (intake_state_ == IntakeState::INTAKE_FRONT_BALL
+ ? constants::Values::kTransferRollerFrontVoltage()
+ : constants::Values::kTransferRollerBackVoltage());
+ flipper_arms_voltage = constants::Values::kFlipperFeedVoltage();
+
+ // Ball is in catapult
+ if (position->turret_beambreak()) {
+ intake_state_ = IntakeState::NO_BALL;
+ state_ = SuperstructureState::LOADING;
+ loading_timer_ = timestamp;
+ }
+ break;
+ }
+ case SuperstructureState::LOADING: {
+ flipper_arms_voltage = constants::Values::kFlipperFeedVoltage();
+
+ // Keep feeding for kExtraLoadingTime
+
+ can_position_fetcher_.Fetch();
+ const bool flipper_arm_roller_is_stopped =
+ can_position_fetcher_.get() != nullptr &&
+ std::abs(
+ can_position_fetcher_->flipper_arm_integrated_sensor_velocity()) <
+ 0.01;
+
+ const bool reading_is_recent =
+ can_position_fetcher_.get() != nullptr &&
+ (timestamp < can_position_fetcher_.context().monotonic_event_time +
+ constants::Values::kFlipperVelocityValidTime());
+
+ // The ball should go past the turret beambreak to be loaded.
+ // If we got a CAN reading not too long ago, the flippers should have also
+ // stopped.
+ // TODO(milind): maybe it's better to update loading_timer_ as long as the
+ // turret beambreak is triggered.
+ if (timestamp > loading_timer_ + constants::Values::kExtraLoadingTime() &&
+ !position->turret_beambreak() &&
+ (flipper_arm_roller_is_stopped || !reading_is_recent)) {
+ state_ = SuperstructureState::LOADED;
+ reseating_in_catapult_ = false;
+ }
+ break;
+ }
+ case SuperstructureState::LOADED: {
+ if (unsafe_goal != nullptr) {
+ if (unsafe_goal->cancel_shot()) {
+ // Cancel the shot process
+ state_ = SuperstructureState::IDLE;
+ } else if (unsafe_goal->fire()) {
+ // Start if we were asked to and the turret is at goal
+ state_ = SuperstructureState::SHOOTING;
+ prev_shot_count_ = catapult_.shot_count();
+
+ // Reset opening timeout
+ flipper_opening_start_time_ = timestamp;
+ }
+ }
+ break;
+ }
+ case SuperstructureState::SHOOTING: {
+ // Opening flipper arms could fail, wait until they are open using their
+ // potentiometers (the member below is just named encoder).
+ // Be a little more lenient if the flippers were already open in case of
+ // noise or collisions.
+ const double flipper_open_position =
+ (flippers_open_ ? constants::Values::kReseatFlipperPosition()
+ : constants::Values::kFlipperOpenPosition());
+ flippers_open_ =
+ position->flipper_arm_left()->encoder() >= flipper_open_position &&
+ position->flipper_arm_right()->encoder() >= flipper_open_position;
+
+ if (flippers_open_) {
+ // Hold at kFlipperHoldVoltage
+ flipper_arms_voltage = constants::Values::kFlipperHoldVoltage();
+ } else {
+ // Open at kFlipperOpenVoltage
+ flipper_arms_voltage = constants::Values::kFlipperOpenVoltage();
+ }
+
+ if (!flippers_open_ &&
+ timestamp >
+ loading_timer_ + constants::Values::kFlipperOpeningTimeout()) {
+ // Reseat the ball and try again
+ state_ = SuperstructureState::LOADING;
+ loading_timer_ = timestamp;
+ reseating_in_catapult_ = true;
+ break;
+ }
+
+ const bool turret_near_goal =
+ turret_goal != nullptr &&
+ std::abs(turret_goal->unsafe_goal() - turret_.position()) <
+ kTurretGoalThreshold;
+
+ // If the turret reached the aiming goal, fire!
+ if (flippers_open_ && turret_near_goal) {
+ fire_ = true;
+ }
+
+ // If we started firing and the flippers closed a bit, estop to prevent
+ // damage
+ if (fire_ && !flippers_open_) {
+ catapult_.Estop();
+ }
+
+ const bool near_return_position =
+ (unsafe_goal != nullptr && unsafe_goal->has_catapult() &&
+ unsafe_goal->catapult()->has_return_position() &&
+ std::abs(unsafe_goal->catapult()->return_position()->unsafe_goal() -
+ catapult_.estimated_position()) < kCatapultGoalThreshold);
+
+ // Once the shot is complete and the catapult is back to its return
+ // position, go back to IDLE
+ if (catapult_.shot_count() > prev_shot_count_ && near_return_position) {
+ prev_shot_count_ = catapult_.shot_count();
+ fire_ = false;
+ state_ = SuperstructureState::IDLE;
+ }
+
+ break;
+ }
+ }
+
+ collision_avoidance_.UpdateGoal(
+ {.intake_front_position = intake_front_.estimated_position(),
+ .intake_back_position = intake_back_.estimated_position(),
+ .turret_position = turret_.estimated_position()},
+ turret_goal);
+
+ turret_.set_min_position(collision_avoidance_.min_turret_goal());
+ turret_.set_max_position(collision_avoidance_.max_turret_goal());
+ intake_front_.set_min_position(collision_avoidance_.min_intake_front_goal());
+ intake_front_.set_max_position(collision_avoidance_.max_intake_front_goal());
+ intake_back_.set_min_position(collision_avoidance_.min_intake_back_goal());
+ intake_back_.set_max_position(collision_avoidance_.max_intake_back_goal());
+
+ // Disable the catapult if we want to restart to prevent damage with flippers
const flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
- catapult_status_offset = catapult_.Iterate(
- unsafe_goal, position,
- output != nullptr ? &(output_struct.catapult_voltage) : nullptr,
- status->fbb());
+ catapult_status_offset =
+ catapult_.Iterate(unsafe_goal, position,
+ output != nullptr && !catapult_.estopped()
+ ? &(output_struct.catapult_voltage)
+ : nullptr,
+ fire_, status->fbb());
- flatbuffers::Offset<RelativeEncoderProfiledJointStatus>
+ const flatbuffers::Offset<RelativeEncoderProfiledJointStatus>
climber_status_offset = climber_.Iterate(
unsafe_goal != nullptr ? unsafe_goal->climber() : nullptr,
position->climber(),
- output != nullptr ? &(output_struct.climber_voltage) : nullptr,
+ output != nullptr ? &output_struct.climber_voltage : nullptr,
status->fbb());
- flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
+ const flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
intake_status_offset_front = intake_front_.Iterate(
unsafe_goal != nullptr ? unsafe_goal->intake_front() : nullptr,
position->intake_front(),
- output != nullptr ? &(output_struct.intake_voltage_front) : nullptr,
+ output != nullptr ? &output_struct.intake_voltage_front : nullptr,
status->fbb());
- flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
+ const flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
intake_status_offset_back = intake_back_.Iterate(
unsafe_goal != nullptr ? unsafe_goal->intake_back() : nullptr,
position->intake_back(),
- output != nullptr ? &(output_struct.intake_voltage_back) : nullptr,
+ output != nullptr ? &output_struct.intake_voltage_back : nullptr,
status->fbb());
- flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
+ const flatbuffers::Offset<PotAndAbsoluteEncoderProfiledJointStatus>
turret_status_offset = turret_.Iterate(
- unsafe_goal != nullptr ? unsafe_goal->turret() : nullptr,
- position->turret(),
- output != nullptr ? &(output_struct.turret_voltage) : nullptr,
+ turret_goal, position->turret(),
+ output != nullptr ? &output_struct.turret_voltage : nullptr,
status->fbb());
if (output != nullptr) {
output_struct.roller_voltage_front = roller_speed_compensated_front;
output_struct.roller_voltage_back = roller_speed_compensated_back;
output_struct.transfer_roller_voltage = transfer_roller_speed;
+ output_struct.flipper_arms_voltage = flipper_arms_voltage;
output->CheckOk(output->Send(Output::Pack(*output->fbb(), &output_struct)));
}
@@ -121,9 +385,11 @@
Status::Builder status_builder = status->MakeBuilder<Status>();
const bool zeroed = intake_front_.zeroed() && intake_back_.zeroed() &&
- turret_.zeroed() && climber_.zeroed() && catapult_.zeroed();
+ turret_.zeroed() && climber_.zeroed() &&
+ catapult_.zeroed();
const bool estopped = intake_front_.estopped() || intake_back_.estopped() ||
- turret_.estopped() || climber_.estopped() || catapult_.estopped();
+ turret_.estopped() || climber_.estopped() ||
+ catapult_.estopped();
status_builder.add_zeroed(zeroed);
status_builder.add_estopped(estopped);
@@ -132,10 +398,17 @@
status_builder.add_intake_back(intake_status_offset_back);
status_builder.add_turret(turret_status_offset);
status_builder.add_climber(climber_status_offset);
+
status_builder.add_catapult(catapult_status_offset);
status_builder.add_solve_time(catapult_.solve_time());
- status_builder.add_mpc_active(catapult_.mpc_active());
status_builder.add_shot_count(catapult_.shot_count());
+ status_builder.add_mpc_active(catapult_.mpc_active());
+
+ status_builder.add_flippers_open(flippers_open_);
+ status_builder.add_reseating_in_catapult(reseating_in_catapult_);
+ status_builder.add_fire(fire_);
+ status_builder.add_state(state_);
+ status_builder.add_intake_state(intake_state_);
(void)status->Send(status_builder.Finish());
}
diff --git a/y2022/control_loops/superstructure/superstructure.h b/y2022/control_loops/superstructure/superstructure.h
index dfd4265..13a790a 100644
--- a/y2022/control_loops/superstructure/superstructure.h
+++ b/y2022/control_loops/superstructure/superstructure.h
@@ -7,6 +7,7 @@
#include "y2022/constants.h"
#include "y2022/control_loops/superstructure/catapult/catapult.h"
#include "y2022/control_loops/superstructure/collision_avoidance.h"
+#include "y2022/control_loops/superstructure/superstructure_can_position_generated.h"
#include "y2022/control_loops/superstructure/superstructure_goal_generated.h"
#include "y2022/control_loops/superstructure/superstructure_output_generated.h"
#include "y2022/control_loops/superstructure/superstructure_position_generated.h"
@@ -29,6 +30,11 @@
::frc971::zeroing::PotAndAbsoluteEncoderZeroingEstimator,
::frc971::control_loops::PotAndAbsoluteEncoderProfiledJointStatus>;
+ static constexpr double kTurretGoalThreshold = 0.01;
+ static constexpr double kCatapultGoalThreshold = 0.01;
+ // potentiometer will be more noisy
+ static constexpr double kFlipperGoalThreshold = 0.05;
+
explicit Superstructure(::aos::EventLoop *event_loop,
std::shared_ptr<const constants::Values> values,
const ::std::string &name = "/superstructure");
@@ -58,15 +64,32 @@
PotAndAbsoluteEncoderSubsystem intake_front_;
PotAndAbsoluteEncoderSubsystem intake_back_;
PotAndAbsoluteEncoderSubsystem turret_;
+ catapult::Catapult catapult_;
CollisionAvoidance collision_avoidance_;
aos::Fetcher<frc971::control_loops::drivetrain::Status>
drivetrain_status_fetcher_;
+ aos::Fetcher<CANPosition> can_position_fetcher_;
+
+ int prev_shot_count_ = 0;
+
+ bool flippers_open_ = false;
+ bool reseating_in_catapult_ = false;
+ bool fire_ = false;
+
+ aos::monotonic_clock::time_point intake_beambreak_timer_ =
+ aos::monotonic_clock::min_time;
+ aos::monotonic_clock::time_point transferring_timer_ =
+ aos::monotonic_clock::min_time;
+ aos::monotonic_clock::time_point loading_timer_ =
+ aos::monotonic_clock::min_time;
+ aos::monotonic_clock::time_point flipper_opening_start_time_ =
+ aos::monotonic_clock::min_time;
+ SuperstructureState state_ = SuperstructureState::IDLE;
+ IntakeState intake_state_ = IntakeState::NO_BALL;
DISALLOW_COPY_AND_ASSIGN(Superstructure);
-
- catapult::Catapult catapult_;
};
} // namespace superstructure
diff --git a/y2022/control_loops/superstructure/superstructure_goal.fbs b/y2022/control_loops/superstructure/superstructure_goal.fbs
index ada39a2..379f6ba 100644
--- a/y2022/control_loops/superstructure/superstructure_goal.fbs
+++ b/y2022/control_loops/superstructure/superstructure_goal.fbs
@@ -3,8 +3,9 @@
namespace y2022.control_loops.superstructure;
table CatapultGoal {
- // If true, fire! The robot will only fire when ready.
- fire:bool (id: 0);
+ // Old fire flag, only kept for backwards-compatability with logs.
+ // Use the fire flag in the root Goal instead
+ fire:bool (id: 0, deprecated);
// The target shot position and velocity. If these are provided before fire
// is called, the optimizer can pre-compute the trajectory.
@@ -37,6 +38,15 @@
// Catapult goal state.
catapult:CatapultGoal (id: 8);
+
+ // If true, fire! The robot will only fire when ready.
+ fire:bool (id: 9);
+
+ // Aborts the shooting process if the ball has been loaded into the catapult
+ // and the superstructure is in the LOADED state.
+ cancel_shot:bool (id: 10);
}
+
+
root_type Goal;
diff --git a/y2022/control_loops/superstructure/superstructure_lib_test.cc b/y2022/control_loops/superstructure/superstructure_lib_test.cc
index 06dee7b..7425ac0 100644
--- a/y2022/control_loops/superstructure/superstructure_lib_test.cc
+++ b/y2022/control_loops/superstructure/superstructure_lib_test.cc
@@ -244,6 +244,18 @@
flatbuffers::Offset<frc971::RelativePosition> climber_offset =
climber_.encoder()->GetSensorValues(&climber_builder);
+ frc971::RelativePosition::Builder flipper_arm_left_builder =
+ builder.MakeBuilder<frc971::RelativePosition>();
+ flipper_arm_left_builder.add_encoder(flipper_arm_left_);
+ flatbuffers::Offset<frc971::RelativePosition> flipper_arm_left_offset =
+ flipper_arm_left_builder.Finish();
+
+ frc971::RelativePosition::Builder flipper_arm_right_builder =
+ builder.MakeBuilder<frc971::RelativePosition>();
+ flipper_arm_right_builder.add_encoder(flipper_arm_right_);
+ flatbuffers::Offset<frc971::RelativePosition> flipper_arm_right_offset =
+ flipper_arm_left_builder.Finish();
+
Position::Builder position_builder = builder.MakeBuilder<Position>();
position_builder.add_intake_front(intake_front_offset);
@@ -251,6 +263,11 @@
position_builder.add_turret(turret_offset);
position_builder.add_catapult(catapult_offset);
position_builder.add_climber(climber_offset);
+ position_builder.add_intake_beambreak_front(intake_beambreak_front_);
+ position_builder.add_intake_beambreak_back(intake_beambreak_back_);
+ position_builder.add_turret_beambreak(turret_beambreak_);
+ position_builder.add_flipper_arm_left(flipper_arm_left_offset);
+ position_builder.add_flipper_arm_right(flipper_arm_right_offset);
CHECK_EQ(builder.Send(position_builder.Finish()),
aos::RawSender::Error::kOk);
@@ -262,6 +279,19 @@
PotAndAbsoluteEncoderSimulator *catapult() { return &catapult_; }
RelativeEncoderSimulator *climber() { return &climber_; }
+ void set_intake_beambreak_front(bool triggered) {
+ intake_beambreak_front_ = triggered;
+ }
+
+ void set_intake_beambreak_back(bool triggered) {
+ intake_beambreak_back_ = triggered;
+ }
+
+ void set_turret_beambreak(bool triggered) { turret_beambreak_ = triggered; }
+
+ void set_flipper_arm_left(double pos) { flipper_arm_left_ = pos; }
+ void set_flipper_arm_right(double pos) { flipper_arm_right_ = pos; }
+
private:
::aos::EventLoop *event_loop_;
const chrono::nanoseconds dt_;
@@ -273,6 +303,11 @@
bool first_ = true;
+ bool intake_beambreak_front_ = false;
+ bool intake_beambreak_back_ = false;
+ bool turret_beambreak_ = false;
+ double flipper_arm_left_ = 0.0;
+ double flipper_arm_right_ = 0.0;
PotAndAbsoluteEncoderSimulator intake_front_;
PotAndAbsoluteEncoderSimulator intake_back_;
PotAndAbsoluteEncoderSimulator turret_;
@@ -343,11 +378,6 @@
0.001);
}
- if (superstructure_goal_fetcher_->has_turret()) {
- EXPECT_NEAR(superstructure_goal_fetcher_->turret()->unsafe_goal(),
- superstructure_status_fetcher_->turret()->position(), 0.001);
- }
-
if (superstructure_goal_fetcher_->has_catapult() &&
superstructure_goal_fetcher_->catapult()->has_return_position()) {
EXPECT_NEAR(superstructure_goal_fetcher_->catapult()
@@ -361,7 +391,23 @@
EXPECT_NEAR(superstructure_goal_fetcher_->climber()->unsafe_goal(),
superstructure_status_fetcher_->climber()->position(), 0.001);
}
- }
+
+ if (superstructure_status_fetcher_->intake_state() !=
+ IntakeState::NO_BALL) {
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_front(), 0.0);
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_back(), 0.0);
+ }
+
+ EXPECT_NEAR(superstructure_goal_fetcher_->climber()->unsafe_goal(),
+ superstructure_status_fetcher_->climber()->position(), 0.001);
+
+ if (superstructure_goal_fetcher_->has_turret() &&
+ superstructure_status_fetcher_->state() !=
+ SuperstructureState::TRANSFERRING) {
+ EXPECT_NEAR(superstructure_goal_fetcher_->turret()->unsafe_goal(),
+ superstructure_status_fetcher_->turret()->position(), 0.001);
+ }
+ } // namespace testing
void CheckIfZeroed() {
superstructure_status_fetcher_.Fetch();
@@ -392,7 +438,7 @@
}
void TestRollerFront(double roller_speed_front,
- double roller_speed_compensation) {
+ double roller_speed_compensation, double expected) {
auto builder = superstructure_goal_sender_.MakeBuilder();
Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
goal_builder.add_roller_speed_front(roller_speed_front);
@@ -400,18 +446,11 @@
builder.CheckOk(builder.Send(goal_builder.Finish()));
RunFor(dt() * 2);
ASSERT_TRUE(superstructure_output_fetcher_.Fetch());
- EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_front(),
- roller_speed_front + std::max((superstructure_.robot_velocity() *
- roller_speed_compensation),
- 0.0));
- if (superstructure_.robot_velocity() <= 0) {
- EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_front(),
- roller_speed_front);
- }
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_front(), expected);
}
void TestRollerBack(double roller_speed_back,
- double roller_speed_compensation) {
+ double roller_speed_compensation, double expected) {
auto builder = superstructure_goal_sender_.MakeBuilder();
Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
goal_builder.add_roller_speed_back(roller_speed_back);
@@ -420,18 +459,12 @@
RunFor(dt() * 2);
ASSERT_TRUE(superstructure_output_fetcher_.Fetch());
ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
- EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_back(),
- roller_speed_back - std::min(superstructure_.robot_velocity() *
- roller_speed_compensation,
- 0.0));
- if (superstructure_.robot_velocity() >= 0) {
- EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_back(),
- roller_speed_back);
- }
+
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_back(), expected);
}
void TestTransferRoller(double transfer_roller_speed,
- double roller_speed_compensation) {
+ double roller_speed_compensation, double expected) {
auto builder = superstructure_goal_sender_.MakeBuilder();
Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
goal_builder.add_transfer_roller_speed(transfer_roller_speed);
@@ -441,7 +474,7 @@
ASSERT_TRUE(superstructure_output_fetcher_.Fetch());
ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
EXPECT_EQ(superstructure_output_fetcher_->transfer_roller_voltage(),
- transfer_roller_speed);
+ expected);
}
std::shared_ptr<const constants::Values> values_;
@@ -466,7 +499,7 @@
std::unique_ptr<aos::EventLoop> logger_event_loop_;
std::unique_ptr<aos::logger::Logger> logger_;
-};
+}; // namespace testing
// Tests that the superstructure does nothing when the goal is to remain
// still.
@@ -537,22 +570,22 @@
auto builder = superstructure_goal_sender_.MakeBuilder();
flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
intake_offset_front = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
- *builder.fbb(), constants::Values::kIntakeRange().upper,
+ *builder.fbb(), constants::Values::kIntakeRange().lower,
CreateProfileParameters(*builder.fbb(), 1.0, 0.2));
flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
intake_offset_back = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
- *builder.fbb(), constants::Values::kIntakeRange().upper,
+ *builder.fbb(), constants::Values::kIntakeRange().lower,
CreateProfileParameters(*builder.fbb(), 1.0, 0.2));
flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
turret_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
- *builder.fbb(), constants::Values::kTurretRange().upper,
+ *builder.fbb(), constants::Values::kTurretRange().lower,
CreateProfileParameters(*builder.fbb(), 1.0, 0.2));
flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
climber_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
- *builder.fbb(), constants::Values::kClimberRange().upper,
+ *builder.fbb(), constants::Values::kClimberRange().lower,
CreateProfileParameters(*builder.fbb(), 1.0, 0.2));
Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
@@ -587,11 +620,11 @@
flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
intake_offset_front = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
- *builder.fbb(), constants::Values::kIntakeRange().lower);
+ *builder.fbb(), constants::Values::kIntakeRange().upper);
flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
intake_offset_back = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
- *builder.fbb(), constants::Values::kIntakeRange().lower);
+ *builder.fbb(), constants::Values::kIntakeRange().upper);
// Keep the turret away from the intakes because they start in the collision
// area
@@ -601,7 +634,7 @@
flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
climber_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
- *builder.fbb(), constants::Values::kClimberRange().lower);
+ *builder.fbb(), constants::Values::kClimberRange().upper);
Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
@@ -624,22 +657,22 @@
flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
intake_offset_front = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
- *builder.fbb(), constants::Values::kIntakeRange().upper,
+ *builder.fbb(), constants::Values::kIntakeRange().lower,
CreateProfileParameters(*builder.fbb(), 20.0, 0.1));
flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
intake_offset_back = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
- *builder.fbb(), constants::Values::kIntakeRange().upper,
+ *builder.fbb(), constants::Values::kIntakeRange().lower,
CreateProfileParameters(*builder.fbb(), 20.0, 0.1));
flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
turret_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
- *builder.fbb(), constants::Values::kTurretRange().upper,
+ *builder.fbb(), constants::Values::kTurretRange().lower,
CreateProfileParameters(*builder.fbb(), 20.0, 0.1));
flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
climber_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
- *builder.fbb(), constants::Values::kClimberRange().upper,
+ *builder.fbb(), constants::Values::kClimberRange().lower,
CreateProfileParameters(*builder.fbb(), 20.0, 0.1));
Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
@@ -699,28 +732,265 @@
WaitUntilZeroed();
SendRobotVelocity(3.0);
- TestRollerFront(-12.0, 1.5);
- TestRollerFront(12.0, 1.5);
- TestRollerFront(0.0, 1.5);
+ TestRollerFront(-12.0, 1.5, -7.5);
+ TestRollerFront(12.0, 1.5, 16.5);
+ TestRollerFront(0.0, 1.5, 4.5);
SendRobotVelocity(-3.0);
- TestRollerFront(-12.0, 1.5);
- TestRollerFront(12.0, 1.5);
- TestRollerFront(0.0, 1.5);
+ TestRollerFront(-12.0, 1.5, -12.0);
+ TestRollerFront(12.0, 1.5, 12.0);
+ TestRollerFront(0.0, 1.5, 0.0);
SendRobotVelocity(3.0);
- TestRollerBack(-12.0, 1.5);
- TestRollerBack(12.0, 1.5);
- TestRollerBack(0.0, 1.5);
+ TestRollerBack(-12.0, 1.5, -12.0);
+ TestRollerBack(12.0, 1.5, 12.0);
+ TestRollerBack(0.0, 1.5, 0.0);
SendRobotVelocity(-3.0);
- TestRollerBack(-12.0, 1.5);
- TestRollerBack(12.0, 1.5);
- TestRollerBack(0.0, 1.5);
+ TestRollerBack(-12.0, 1.5, -7.5);
+ TestRollerBack(12.0, 1.5, 16.5);
+ TestRollerBack(0.0, 1.5, 4.5);
- TestTransferRoller(-12.0, 1.5);
- TestTransferRoller(12.0, 1.5);
- TestTransferRoller(0.0, 1.5);
+ TestTransferRoller(-12.0, 1.5, -12.0);
+ TestTransferRoller(12.0, 1.5, 12.0);
+ TestTransferRoller(0.0, 1.5, 0.0);
+}
+
+// Tests the whole shooting statemachine - from loading to shooting
+TEST_F(SuperstructureTest, LoadingToShooting) {
+ SetEnabled(true);
+ WaitUntilZeroed();
+
+ SendRobotVelocity(3.0);
+
+ constexpr double kTurretGoal = 3.0;
+ {
+ auto builder = superstructure_goal_sender_.MakeBuilder();
+ flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
+ turret_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
+ *builder.fbb(), kTurretGoal);
+ Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+ goal_builder.add_roller_speed_front(12.0);
+ goal_builder.add_roller_speed_back(12.0);
+ goal_builder.add_roller_speed_compensation(0.0);
+ goal_builder.add_turret(turret_offset);
+ builder.CheckOk(builder.Send(goal_builder.Finish()));
+ }
+ RunFor(std::chrono::seconds(2));
+
+ // Make sure that the rollers are spinning, but the superstructure hasn't
+ // transitioned away from idle because the beambreaks haven't been triggered.
+ ASSERT_TRUE(superstructure_output_fetcher_.Fetch());
+ ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_front(), 12.0);
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_back(), 12.0);
+ EXPECT_EQ(superstructure_output_fetcher_->transfer_roller_voltage(), 0.0);
+ EXPECT_EQ(superstructure_status_fetcher_->state(), SuperstructureState::IDLE);
+ EXPECT_EQ(superstructure_status_fetcher_->intake_state(),
+ IntakeState::NO_BALL);
+ EXPECT_NEAR(superstructure_status_fetcher_->turret()->position(), kTurretGoal,
+ 0.001);
+ EXPECT_EQ(superstructure_status_fetcher_->shot_count(), 0);
+
+ superstructure_plant_.set_intake_beambreak_front(true);
+ superstructure_plant_.set_intake_beambreak_back(false);
+ RunFor(dt());
+
+ // Make sure that the turret goal is set to be loading from the front intake
+ // and the supersturcture is transferring from the front intake, since that
+ // beambreak was trigerred. Also, the outside rollers should be stopped
+ ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
+ ASSERT_TRUE(superstructure_output_fetcher_.Fetch());
+ EXPECT_EQ(superstructure_status_fetcher_->state(),
+ SuperstructureState::TRANSFERRING);
+ EXPECT_EQ(superstructure_status_fetcher_->intake_state(),
+ IntakeState::INTAKE_FRONT_BALL);
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_front(), 0.0);
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_back(), 0.0);
+
+ RunFor(chrono::seconds(1));
+
+ // Make sure that we are still transferring and the front transfer rollers
+ // still have a ball. The turret should now be at the loading position and the
+ // flippers should be feeding the ball.
+ ASSERT_TRUE(superstructure_output_fetcher_.Fetch());
+ ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_front(), 0.0);
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_back(), 0.0);
+ EXPECT_EQ(superstructure_status_fetcher_->state(),
+ SuperstructureState::TRANSFERRING);
+ EXPECT_EQ(superstructure_status_fetcher_->intake_state(),
+ IntakeState::INTAKE_FRONT_BALL);
+ EXPECT_EQ(superstructure_output_fetcher_->flipper_arms_voltage(),
+ constants::Values::kFlipperFeedVoltage());
+ EXPECT_EQ(superstructure_output_fetcher_->transfer_roller_voltage(),
+ constants::Values::kTransferRollerFrontVoltage());
+ EXPECT_NEAR(superstructure_status_fetcher_->turret()->position(),
+ constants::Values::kTurretFrontIntakePos(), 0.001);
+ EXPECT_EQ(superstructure_status_fetcher_->shot_count(), 0);
+
+ superstructure_plant_.set_intake_beambreak_front(false);
+ superstructure_plant_.set_intake_beambreak_back(false);
+ superstructure_plant_.set_turret_beambreak(true);
+ RunFor(dt() * 2);
+
+ // Now that the turret beambreak has been triggered, we should be loading the
+ // ball. The outside rollers shouldn't be limited anymore, and the transfer
+ // rollers should be off. The flippers should still be feeding the ball, and
+ // the intake state should reflect that the ball has been transferred away
+ ASSERT_TRUE(superstructure_output_fetcher_.Fetch());
+ ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_front(), 12.0);
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_back(), 12.0);
+ EXPECT_EQ(superstructure_output_fetcher_->transfer_roller_voltage(), 0.0);
+ EXPECT_EQ(superstructure_status_fetcher_->state(),
+ SuperstructureState::LOADING);
+ EXPECT_EQ(superstructure_status_fetcher_->intake_state(),
+ IntakeState::NO_BALL);
+ EXPECT_EQ(superstructure_output_fetcher_->flipper_arms_voltage(),
+ constants::Values::kFlipperFeedVoltage());
+ EXPECT_EQ(superstructure_status_fetcher_->shot_count(), 0);
+
+ superstructure_plant_.set_turret_beambreak(false);
+ RunFor(constants::Values::kExtraLoadingTime() + dt());
+
+ // Now that the ball has gone past the turret beambreak,
+ // it should be loaded in the catapult and ready for firing.
+ // The flippers should be off.
+ ASSERT_TRUE(superstructure_output_fetcher_.Fetch());
+ ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_front(), 12.0);
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_back(), 12.0);
+ EXPECT_EQ(superstructure_output_fetcher_->transfer_roller_voltage(), 0.0);
+ EXPECT_EQ(superstructure_status_fetcher_->state(),
+ SuperstructureState::LOADED);
+ EXPECT_EQ(superstructure_status_fetcher_->intake_state(),
+ IntakeState::NO_BALL);
+ EXPECT_EQ(superstructure_output_fetcher_->flipper_arms_voltage(), 0.0);
+ EXPECT_EQ(superstructure_status_fetcher_->shot_count(), 0);
+
+ RunFor(std::chrono::seconds(2));
+
+ // After a few seconds, the turret should be at it's aiming goal. The flippers
+ // should still be off and we should still be loaded and ready to fire.
+ ASSERT_TRUE(superstructure_output_fetcher_.Fetch());
+ ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_front(), 12.0);
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_back(), 12.0);
+ EXPECT_EQ(superstructure_output_fetcher_->transfer_roller_voltage(), 0.0);
+ EXPECT_EQ(superstructure_status_fetcher_->state(),
+ SuperstructureState::LOADED);
+ EXPECT_EQ(superstructure_status_fetcher_->intake_state(),
+ IntakeState::NO_BALL);
+ EXPECT_EQ(superstructure_output_fetcher_->flipper_arms_voltage(), 0.0);
+ EXPECT_NEAR(superstructure_status_fetcher_->turret()->position(), kTurretGoal,
+ 0.001);
+ EXPECT_EQ(superstructure_status_fetcher_->shot_count(), 0);
+
+ superstructure_plant_.set_intake_beambreak_front(false);
+ superstructure_plant_.set_intake_beambreak_back(true);
+ RunFor(dt() * 2);
+
+ // A ball being intaked from the back should be held by wiggling the transfer
+ // rollers, but we shound't abort the shot from the front intake for it and
+ // move the turret.
+ ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
+ ASSERT_TRUE(superstructure_output_fetcher_.Fetch());
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_front(), 0.0);
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_back(), 0.0);
+ LOG(INFO) << superstructure_output_fetcher_->transfer_roller_voltage();
+ EXPECT_TRUE(superstructure_output_fetcher_->transfer_roller_voltage() !=
+ 0.0 &&
+ superstructure_output_fetcher_->transfer_roller_voltage() <=
+ constants::Values::kTransferRollerFrontWiggleVoltage() &&
+ superstructure_output_fetcher_->transfer_roller_voltage() >=
+ -constants::Values::kTransferRollerFrontWiggleVoltage());
+ EXPECT_EQ(superstructure_status_fetcher_->state(),
+ SuperstructureState::LOADED);
+ EXPECT_EQ(superstructure_status_fetcher_->intake_state(),
+ IntakeState::INTAKE_BACK_BALL);
+ EXPECT_NEAR(superstructure_status_fetcher_->turret()->position(), kTurretGoal,
+ 0.001);
+
+ {
+ auto builder = superstructure_goal_sender_.MakeBuilder();
+ flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
+ turret_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
+ *builder.fbb(), kTurretGoal);
+
+ const auto catapult_return_offset =
+ CreateStaticZeroingSingleDOFProfiledSubsystemGoal(*builder.fbb(),
+ -0.87);
+ auto catapult_builder = builder.MakeBuilder<CatapultGoal>();
+ catapult_builder.add_shot_position(0.3);
+ catapult_builder.add_shot_velocity(15.0);
+ catapult_builder.add_return_position(catapult_return_offset);
+ auto catapult_offset = catapult_builder.Finish();
+
+ Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+ goal_builder.add_roller_speed_front(12.0);
+ goal_builder.add_roller_speed_back(12.0);
+ goal_builder.add_roller_speed_compensation(0.0);
+ goal_builder.add_catapult(catapult_offset);
+ goal_builder.add_fire(true);
+ goal_builder.add_turret(turret_offset);
+ builder.CheckOk(builder.Send(goal_builder.Finish()));
+ }
+ superstructure_plant_.set_flipper_arm_left(
+ constants::Values::kFlipperArmRange().upper);
+ superstructure_plant_.set_flipper_arm_right(
+ constants::Values::kFlipperArmRange().upper);
+ RunFor(dt() * 2);
+
+ // Now that we were asked to fire and the flippers are open,
+ // we should be shooting the ball and holding the flippers open.
+ // The turret should still be at its goal, and we should still be wiggling the
+ // transfer rollers to keep the ball in the back intake
+ ASSERT_TRUE(superstructure_output_fetcher_.Fetch());
+ ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_front(), 0.0);
+ EXPECT_EQ(superstructure_output_fetcher_->roller_voltage_back(), 0.0);
+ EXPECT_TRUE(superstructure_output_fetcher_->transfer_roller_voltage() !=
+ 0.0 &&
+ superstructure_output_fetcher_->transfer_roller_voltage() <=
+ constants::Values::kTransferRollerFrontWiggleVoltage() &&
+ superstructure_output_fetcher_->transfer_roller_voltage() >=
+ -constants::Values::kTransferRollerFrontWiggleVoltage());
+ EXPECT_EQ(superstructure_status_fetcher_->state(),
+ SuperstructureState::SHOOTING);
+ EXPECT_EQ(superstructure_status_fetcher_->intake_state(),
+ IntakeState::INTAKE_BACK_BALL);
+ EXPECT_TRUE(superstructure_status_fetcher_->flippers_open());
+ EXPECT_EQ(superstructure_output_fetcher_->flipper_arms_voltage(),
+ constants::Values::kFlipperHoldVoltage());
+ EXPECT_NEAR(superstructure_status_fetcher_->turret()->position(), kTurretGoal,
+ 0.001);
+ EXPECT_EQ(superstructure_status_fetcher_->shot_count(), 0);
+
+ superstructure_plant_.set_flipper_arm_left(
+ constants::Values::kFlipperArmRange().upper);
+ superstructure_plant_.set_flipper_arm_right(
+ constants::Values::kFlipperArmRange().upper);
+ superstructure_plant_.set_intake_beambreak_back(false);
+ RunFor(std::chrono::seconds(2));
+
+ // After a bit, we should have completed the shot and be idle.
+ // Since the beambreak was triggered a bit ago, it should still think a ball
+ // is there
+ ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
+ EXPECT_EQ(superstructure_status_fetcher_->shot_count(), 1);
+ EXPECT_EQ(superstructure_status_fetcher_->state(), SuperstructureState::IDLE);
+ EXPECT_EQ(superstructure_status_fetcher_->intake_state(),
+ IntakeState::INTAKE_BACK_BALL);
+
+ // Since the intake beambreak hasn't triggered in a while, it should realize
+ // the ball was lost
+ RunFor(std::chrono::seconds(1));
+ ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
+ EXPECT_EQ(superstructure_status_fetcher_->shot_count(), 1);
+ EXPECT_EQ(superstructure_status_fetcher_->state(), SuperstructureState::IDLE);
+ EXPECT_EQ(superstructure_status_fetcher_->intake_state(),
+ IntakeState::NO_BALL);
}
// Make sure that the front and back intakes are never switched
@@ -776,9 +1046,11 @@
TEST_F(SuperstructureTest, ShootCatapult) {
SetEnabled(true);
superstructure_plant_.intake_front()->InitializePosition(
- constants::Values::kIntakeRange().middle());
+ constants::Values::kIntakeRange().upper);
superstructure_plant_.intake_back()->InitializePosition(
- constants::Values::kIntakeRange().middle());
+ constants::Values::kIntakeRange().upper);
+ superstructure_plant_.turret()->InitializePosition(
+ constants::Values::kTurretFrontIntakePos());
WaitUntilZeroed();
@@ -794,7 +1066,6 @@
CatapultGoal::Builder catapult_goal_builder =
builder.MakeBuilder<CatapultGoal>();
- catapult_goal_builder.add_fire(false);
catapult_goal_builder.add_shot_position(0.3);
catapult_goal_builder.add_shot_velocity(15.0);
catapult_goal_builder.add_return_position(catapult_return_position_offset);
@@ -802,6 +1073,7 @@
catapult_goal_builder.Finish();
Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+ goal_builder.add_fire(false);
goal_builder.add_catapult(catapult_goal_offset);
ASSERT_EQ(builder.Send(goal_builder.Finish()), aos::RawSender::Error::kOk);
}
@@ -817,6 +1089,10 @@
auto builder = superstructure_goal_sender_.MakeBuilder();
flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
+ turret_goal_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
+ *builder.fbb(), constants::Values::kTurretFrontIntakePos());
+
+ flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
catapult_return_position_offset =
CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
*builder.fbb(), constants::Values::kCatapultRange().lower,
@@ -825,7 +1101,6 @@
CatapultGoal::Builder catapult_goal_builder =
builder.MakeBuilder<CatapultGoal>();
- catapult_goal_builder.add_fire(true);
catapult_goal_builder.add_shot_position(0.5);
catapult_goal_builder.add_shot_velocity(20.0);
catapult_goal_builder.add_return_position(catapult_return_position_offset);
@@ -834,11 +1109,28 @@
Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+ goal_builder.add_fire(true);
goal_builder.add_catapult(catapult_goal_offset);
+ goal_builder.add_turret(turret_goal_offset);
ASSERT_EQ(builder.Send(goal_builder.Finish()), aos::RawSender::Error::kOk);
}
- RunFor(chrono::milliseconds(100));
+ // Make the superstructure statemachine progress to SHOOTING
+ superstructure_plant_.set_intake_beambreak_front(true);
+ superstructure_plant_.set_turret_beambreak(true);
+ superstructure_plant_.set_flipper_arm_left(
+ constants::Values::kFlipperArmRange().upper);
+ superstructure_plant_.set_flipper_arm_right(
+ constants::Values::kFlipperArmRange().upper);
+
+ RunFor(dt() * 4);
+
+ ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
+ EXPECT_EQ(superstructure_status_fetcher_->state(),
+ SuperstructureState::LOADING);
+ superstructure_plant_.set_turret_beambreak(false);
+
+ RunFor(chrono::milliseconds(200));
ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
EXPECT_TRUE(superstructure_status_fetcher_->mpc_active());
@@ -846,12 +1138,17 @@
EXPECT_GT(superstructure_status_fetcher_->catapult()->position(),
constants::Values::kCatapultRange().lower + 0.1);
+ EXPECT_EQ(superstructure_status_fetcher_->state(),
+ SuperstructureState::SHOOTING);
+ superstructure_plant_.set_intake_beambreak_front(false);
+
RunFor(chrono::milliseconds(1950));
ASSERT_TRUE(superstructure_status_fetcher_.Fetch());
EXPECT_NEAR(superstructure_status_fetcher_->catapult()->position(),
constants::Values::kCatapultRange().lower, 1e-3);
EXPECT_EQ(superstructure_status_fetcher_->shot_count(), 1);
+ EXPECT_EQ(superstructure_status_fetcher_->state(), SuperstructureState::IDLE);
}
} // namespace testing
diff --git a/y2022/control_loops/superstructure/superstructure_output.fbs b/y2022/control_loops/superstructure/superstructure_output.fbs
index a673361..8fa992e 100644
--- a/y2022/control_loops/superstructure/superstructure_output.fbs
+++ b/y2022/control_loops/superstructure/superstructure_output.fbs
@@ -23,6 +23,7 @@
intake_voltage_back:double (id: 5);
// Intake roller voltages
+ // positive is pulling into the robot
roller_voltage_front:double (id: 6);
roller_voltage_back:double (id: 7);
// One transfer motor for both sides
diff --git a/y2022/control_loops/superstructure/superstructure_position.fbs b/y2022/control_loops/superstructure/superstructure_position.fbs
index 46dd547..ba47662 100644
--- a/y2022/control_loops/superstructure/superstructure_position.fbs
+++ b/y2022/control_loops/superstructure/superstructure_position.fbs
@@ -4,14 +4,14 @@
table Position {
climber:frc971.RelativePosition (id: 0);
- // Zero for the intake position value is up, and positive is
- // down.
+ // Zero for the intake position value is horizontal, and positive is
+ // up.
intake_front:frc971.PotAndAbsolutePosition (id: 1);
intake_back:frc971.PotAndAbsolutePosition (id: 2);
- // Zero is forwards; positive = counter-clockwise.
+ // Zero is to the front (away from the RIO); positive = counter-clockwise.
turret:frc971.PotAndAbsolutePosition (id: 3);
- // Zero is straight and positive is open
+ // Zero is closed and positive is open
flipper_arm_left:frc971.RelativePosition (id: 4);
flipper_arm_right:frc971.RelativePosition (id: 5);
diff --git a/y2022/control_loops/superstructure/superstructure_status.fbs b/y2022/control_loops/superstructure/superstructure_status.fbs
index 4487f1d..c74cbab 100644
--- a/y2022/control_loops/superstructure/superstructure_status.fbs
+++ b/y2022/control_loops/superstructure/superstructure_status.fbs
@@ -3,12 +3,47 @@
namespace y2022.control_loops.superstructure;
+// Contains which intake has a ball
+enum IntakeState : ubyte {
+ NO_BALL,
+ INTAKE_FRONT_BALL,
+ INTAKE_BACK_BALL,
+}
+
+// State of the superstructure state machine
+enum SuperstructureState : ubyte {
+ // Before a ball is intaked, when neither intake beambreak is triggered
+ IDLE,
+ // Transferring ball with transfer rollers. Moves turret to loading position.
+ TRANSFERRING,
+ // Loading the ball into the catapult
+ LOADING,
+ // The ball is loaded into the catapult
+ LOADED,
+ // Waiting for the turret to be at shooting goal and then telling the
+ // catapult to fire.
+ SHOOTING,
+}
+
table Status {
// All subsystems know their location.
zeroed:bool (id: 0);
// If true, we have aborted. This is the or of all subsystem estops.
estopped:bool (id: 1);
+ // The state of the superstructure
+
+ state:SuperstructureState (id: 10);
+ // Intaking state
+ intake_state:IntakeState (id: 11);
+ // Whether the flippers are open for shooting
+ flippers_open:bool (id: 12);
+ // Whether the flippers failed to open and we are retrying
+ reseating_in_catapult:bool (id: 13);
+ // Whether the catapult was told to fire,
+ // meaning that the turret and flippers are ready for firing
+ // and we were asked to fire. Different from fire flag in goal.
+ fire:bool (id: 14);
// Subsystem statuses
climber:frc971.control_loops.RelativeEncoderProfiledJointStatus (id: 2);
diff --git a/y2022/control_loops/superstructure/turret_plotter.ts b/y2022/control_loops/superstructure/turret_plotter.ts
new file mode 100644
index 0000000..10fc10e
--- /dev/null
+++ b/y2022/control_loops/superstructure/turret_plotter.ts
@@ -0,0 +1,46 @@
+// Provides a plot for debugging robot state-related issues.
+import {AosPlotter} from 'org_frc971/aos/network/www/aos_plotter';
+import * as proxy from 'org_frc971/aos/network/www/proxy';
+import {BLUE, BROWN, CYAN, GREEN, PINK, RED, WHITE, ORANGE} from 'org_frc971/aos/network/www/colors';
+
+import Connection = proxy.Connection;
+
+const TIME = AosPlotter.TIME;
+const DEFAULT_WIDTH = AosPlotter.DEFAULT_WIDTH * 5 / 2;
+const DEFAULT_HEIGHT = AosPlotter.DEFAULT_HEIGHT * 3;
+
+export function plotTurret(conn: Connection, element: Element) : void {
+ const aosPlotter = new AosPlotter(conn);
+ const goal = aosPlotter.addMessageSource('/superstructure', 'y2022.control_loops.superstructure.Goal');
+ const output = aosPlotter.addMessageSource('/superstructure', 'y2022.control_loops.superstructure.Output');
+ const status = aosPlotter.addMessageSource('/superstructure', 'y2022.control_loops.superstructure.Status');
+ const robotState = aosPlotter.addMessageSource('/aos', 'aos.RobotState');
+
+ // Robot Enabled/Disabled and Mode
+ const positionPlot =
+ aosPlotter.addPlot(element, [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ positionPlot.plot.getAxisLabels().setTitle('Position');
+ positionPlot.plot.getAxisLabels().setXLabel(TIME);
+ positionPlot.plot.getAxisLabels().setYLabel('rad');
+ positionPlot.plot.setDefaultYRange([-1.0, 2.0]);
+
+ positionPlot.addMessageLine(status, ['turret', 'position']).setColor(GREEN).setPointSize(4.0);
+ positionPlot.addMessageLine(status, ['turret', 'velocity']).setColor(PINK).setPointSize(1.0);
+ positionPlot.addMessageLine(status, ['turret', 'goal_position']).setColor(RED).setPointSize(4.0);
+ positionPlot.addMessageLine(status, ['turret', 'goal_velocity']).setColor(ORANGE).setPointSize(4.0);
+ positionPlot.addMessageLine(status, ['turret', 'estimator_state', 'position']).setColor(CYAN).setPointSize(1.0);
+
+ const voltagePlot =
+ aosPlotter.addPlot(element, [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ voltagePlot.plot.getAxisLabels().setTitle('Voltage');
+ voltagePlot.plot.getAxisLabels().setXLabel(TIME);
+ voltagePlot.plot.getAxisLabels().setYLabel('Volts');
+ voltagePlot.plot.setDefaultYRange([-4.0, 14.0]);
+
+ voltagePlot.addMessageLine(output, ['turret_voltage']).setColor(BLUE).setPointSize(4.0);
+ voltagePlot.addMessageLine(status, ['turret', 'voltage_error']).setColor(RED).setPointSize(1.0);
+ voltagePlot.addMessageLine(status, ['turret', 'position_power']).setColor(BROWN).setPointSize(1.0);
+ voltagePlot.addMessageLine(status, ['turret', 'velocity_power']).setColor(CYAN).setPointSize(1.0);
+ voltagePlot.addMessageLine(robotState, ['voltage_battery']).setColor(GREEN).setPointSize(1.0);
+
+}
diff --git a/y2022/joystick_reader.cc b/y2022/joystick_reader.cc
index a39c130..7170a1d 100644
--- a/y2022/joystick_reader.cc
+++ b/y2022/joystick_reader.cc
@@ -10,15 +10,21 @@
#include "aos/network/team_number.h"
#include "aos/util/log_interval.h"
#include "frc971/autonomous/base_autonomous_actor.h"
+#include "frc971/control_loops/drivetrain/localizer_generated.h"
#include "frc971/control_loops/profiled_subsystem_generated.h"
#include "frc971/input/action_joystick_input.h"
#include "frc971/input/driver_station_data.h"
#include "frc971/input/drivetrain_input.h"
#include "frc971/input/joystick_input.h"
+#include "frc971/zeroing/wrap.h"
+#include "y2022/constants.h"
#include "y2022/control_loops/drivetrain/drivetrain_base.h"
#include "y2022/control_loops/superstructure/superstructure_goal_generated.h"
#include "y2022/control_loops/superstructure/superstructure_status_generated.h"
+#include "y2022/setpoint_generated.h"
+using frc971::CreateProfileParameters;
+using frc971::control_loops::CreateStaticZeroingSingleDOFProfiledSubsystemGoal;
using frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemGoal;
using frc971::input::driver_station::ButtonLocation;
using frc971::input::driver_station::ControlBit;
@@ -29,11 +35,24 @@
namespace input {
namespace joysticks {
-const ButtonLocation kCatapultPos(3, 3);
-const ButtonLocation kFire(3, 1);
-
namespace superstructure = y2022::control_loops::superstructure;
+// TODO(henry) put actually button locations here
+// TODO(milind): integrate with shooting statemachine and aimer
+const ButtonLocation kCatapultPos(3, 3);
+const ButtonLocation kFire(3, 2);
+const ButtonLocation kFixedTurret(3, 1);
+
+const ButtonLocation kIntakeFrontOut(4, 4);
+const ButtonLocation kIntakeBackOut(4, 3);
+
+const ButtonLocation kRedLocalizerReset(3, 13);
+const ButtonLocation kBlueLocalizerReset(3, 14);
+const ButtonLocation kLocalizerReset(3, 8);
+
+const ButtonLocation kClimberUpMidRung(10, 10);
+const ButtonLocation kClimberDown(11, 11);
+
class Reader : public ::frc971::input::ActionJoystickInput {
public:
Reader(::aos::EventLoop *event_loop)
@@ -43,9 +62,74 @@
::frc971::input::DrivetrainInputReader::InputType::kPistol, {}),
superstructure_goal_sender_(
event_loop->MakeSender<superstructure::Goal>("/superstructure")),
+ localizer_control_sender_(
+ event_loop->MakeSender<
+ ::frc971::control_loops::drivetrain::LocalizerControl>(
+ "/drivetrain")),
superstructure_status_fetcher_(
- event_loop->MakeFetcher<superstructure::Status>(
- "/superstructure")) {}
+ event_loop->MakeFetcher<superstructure::Status>("/superstructure")),
+ setpoint_fetcher_(
+ event_loop->MakeFetcher<Setpoint>("/superstructure")) {}
+
+ void BlueResetLocalizer() {
+ auto builder = localizer_control_sender_.MakeBuilder();
+
+ frc971::control_loops::drivetrain::LocalizerControl::Builder
+ localizer_control_builder = builder.MakeBuilder<
+ frc971::control_loops::drivetrain::LocalizerControl>();
+ localizer_control_builder.add_x(7.4);
+ localizer_control_builder.add_y(-1.7);
+ localizer_control_builder.add_theta_uncertainty(10.0);
+ localizer_control_builder.add_theta(0.0);
+ localizer_control_builder.add_keep_current_theta(false);
+ if (builder.Send(localizer_control_builder.Finish()) !=
+ aos::RawSender::Error::kOk) {
+ AOS_LOG(ERROR, "Failed to reset blue localizer.\n");
+ }
+ }
+
+ void RedResetLocalizer() {
+ auto builder = localizer_control_sender_.MakeBuilder();
+
+ frc971::control_loops::drivetrain::LocalizerControl::Builder
+ localizer_control_builder = builder.MakeBuilder<
+ frc971::control_loops::drivetrain::LocalizerControl>();
+ localizer_control_builder.add_x(-7.4);
+ localizer_control_builder.add_y(1.7);
+ localizer_control_builder.add_theta_uncertainty(10.0);
+ localizer_control_builder.add_theta(M_PI);
+ localizer_control_builder.add_keep_current_theta(false);
+ if (builder.Send(localizer_control_builder.Finish()) !=
+ aos::RawSender::Error::kOk) {
+ AOS_LOG(ERROR, "Failed to reset red localizer.\n");
+ }
+ }
+
+ void ResetLocalizer() {
+ const frc971::control_loops::drivetrain::Status *drivetrain_status =
+ this->drivetrain_status();
+ if (drivetrain_status == nullptr) {
+ return;
+ }
+ // Get the current position
+ // Snap to heading.
+ auto builder = localizer_control_sender_.MakeBuilder();
+
+ // TODO<Henry> Put our starting location here.
+ frc971::control_loops::drivetrain::LocalizerControl::Builder
+ localizer_control_builder = builder.MakeBuilder<
+ frc971::control_loops::drivetrain::LocalizerControl>();
+ localizer_control_builder.add_x(drivetrain_status->x());
+ localizer_control_builder.add_y(drivetrain_status->y());
+ const double new_theta =
+ frc971::zeroing::Wrap(drivetrain_status->theta(), 0, M_PI);
+ localizer_control_builder.add_theta(new_theta);
+ localizer_control_builder.add_theta_uncertainty(10.0);
+ if (builder.Send(localizer_control_builder.Finish()) !=
+ aos::RawSender::Error::kOk) {
+ AOS_LOG(ERROR, "Failed to reset localizer.\n");
+ }
+ }
void AutoEnded() override { AOS_LOG(INFO, "Auto ended.\n"); }
@@ -57,43 +141,169 @@
return;
}
- aos::Sender<superstructure::Goal>::Builder builder =
- superstructure_goal_sender_.MakeBuilder();
+ setpoint_fetcher_.Fetch();
- flatbuffers::Offset<frc971::ProfileParameters> catapult_profile =
- frc971::CreateProfileParameters(*builder.fbb(), 5.0, 30.0);
+ // Default to the intakes in
+ double intake_front_pos = constants::Values::kIntakeRange().lower;
+ double intake_back_pos = constants::Values::kIntakeRange().lower;
- StaticZeroingSingleDOFProfiledSubsystemGoal::Builder
- catapult_return_builder =
- builder.MakeBuilder<StaticZeroingSingleDOFProfiledSubsystemGoal>();
- catapult_return_builder.add_unsafe_goal(
- data.IsPressed(kCatapultPos) ? 0.3 : -0.85);
- catapult_return_builder.add_profile_params(catapult_profile);
- flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
- catapult_return_offset = catapult_return_builder.Finish();
+ double roller_front_speed = 0.0;
+ double roller_back_speed = 0.0;
+ bool roller_speed_compensation = false;
- superstructure::CatapultGoal::Builder catapult_builder =
- builder.MakeBuilder<superstructure::CatapultGoal>();
- catapult_builder.add_return_position(catapult_return_offset);
- catapult_builder.add_fire(data.IsPressed(kFire));
- catapult_builder.add_shot_position(0.3);
- catapult_builder.add_shot_velocity(15.0);
- flatbuffers::Offset<superstructure::CatapultGoal> catapult_offset =
- catapult_builder.Finish();
+ double turret_pos = 0.0;
- superstructure::Goal::Builder goal_builder =
- builder.MakeBuilder<superstructure::Goal>();
- goal_builder.add_catapult(catapult_offset);
+ double catapult_pos = 0.0;
+ double catapult_return_pos = 0.0;
+ double catapult_speed = 0.0;
+ bool fire = false;
- if (builder.Send(goal_builder.Finish()) != aos::RawSender::Error::kOk) {
- AOS_LOG(ERROR, "Sending superstructure goal failed.\n");
+ if (data.IsPressed(kFire)) {
+ fire = true;
+ }
+
+ // Use setpoints for shooting if present
+ if (setpoint_fetcher_.get()) {
+ turret_pos = setpoint_fetcher_->turret();
+
+ catapult_pos = setpoint_fetcher_->catapult_position();
+ catapult_speed = setpoint_fetcher_->catapult_velocity();
+ } else {
+ turret_pos = 0.0;
+
+ catapult_pos = constants::Values::kDefaultCatapultShotPosition();
+ catapult_speed = constants::Values::kDefaultCatapultShotVelocity();
+ }
+
+ // Keep the catapult return position at the shot one if kCatapultPos is
+ // pressed
+ if (data.IsPressed(kCatapultPos)) {
+ catapult_return_pos = catapult_pos;
+ } else {
+ catapult_return_pos = constants::Values::kCatapultReturnPosition();
+ }
+
+ // If either intake is out by enough, always spin the rollers
+ if (superstructure_status_fetcher_.get() &&
+ superstructure_status_fetcher_->intake_front()->zeroed() &&
+ superstructure_status_fetcher_->intake_front()->position() >
+ constants::Values::kIntakeSlightlyOutPosition()) {
+ roller_front_speed =
+ std::max(roller_front_speed,
+ constants::Values::kMinIntakeSlightlyOutRollerSpeed());
+ roller_speed_compensation = true;
+ }
+ if (superstructure_status_fetcher_.get() &&
+ superstructure_status_fetcher_->intake_back()->zeroed() &&
+ superstructure_status_fetcher_->intake_back()->position() >
+ constants::Values::kIntakeSlightlyOutPosition()) {
+ roller_back_speed =
+ std::max(roller_back_speed,
+ constants::Values::kMinIntakeSlightlyOutRollerSpeed());
+ roller_speed_compensation = true;
+ }
+
+ // Extend the intakes and spin the rollers
+ if (data.IsPressed(kIntakeFrontOut)) {
+ intake_front_pos = constants::Values::kIntakeOutPosition();
+ roller_front_speed = constants::Values::kIntakeOutRollerSpeed();
+ roller_speed_compensation = true;
+ }
+ if (data.IsPressed(kIntakeBackOut)) {
+ intake_back_pos = constants::Values::kIntakeOutPosition();
+ roller_back_speed = constants::Values::kIntakeOutRollerSpeed();
+ roller_speed_compensation = true;
+ }
+
+ // Position climber to climb on mid rung
+ if (data.IsPressed(kClimberUpMidRung)) {
+ climber_pos_ = constants::Values::kClimberMidRungHeight();
+ } else if (data.IsPressed(kClimberDown)) {
+ climber_pos_ = 0.0;
+ }
+
+ if (data.PosEdge(kLocalizerReset)) {
+ ResetLocalizer();
+ }
+
+ if (data.PosEdge(kRedLocalizerReset)) {
+ RedResetLocalizer();
+ }
+ if (data.PosEdge(kBlueLocalizerReset)) {
+ BlueResetLocalizer();
+ }
+
+ {
+ auto builder = superstructure_goal_sender_.MakeBuilder();
+
+ flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
+ intake_front_offset =
+ CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
+ *builder.fbb(), intake_front_pos,
+ CreateProfileParameters(*builder.fbb(), 20.0, 70.0));
+ flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
+ intake_back_offset =
+ CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
+ *builder.fbb(), intake_back_pos,
+ CreateProfileParameters(*builder.fbb(), 20.0, 70.0));
+
+ flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
+ turret_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
+ *builder.fbb(), turret_pos,
+ CreateProfileParameters(*builder.fbb(), 6.0, 20.0));
+
+ flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
+ climber_offset = CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
+ *builder.fbb(), climber_pos_,
+ CreateProfileParameters(*builder.fbb(), 6.0, 20.0));
+
+ flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
+ catapult_return_offset =
+ CreateStaticZeroingSingleDOFProfiledSubsystemGoal(
+ *builder.fbb(), catapult_return_pos,
+ frc971::CreateProfileParameters(*builder.fbb(), 5.0, 30.0));
+
+ superstructure::CatapultGoal::Builder catapult_builder =
+ builder.MakeBuilder<superstructure::CatapultGoal>();
+ catapult_builder.add_return_position(catapult_return_offset);
+ catapult_builder.add_shot_position(catapult_pos);
+ catapult_builder.add_shot_velocity(catapult_speed);
+ flatbuffers::Offset<superstructure::CatapultGoal> catapult_offset =
+ catapult_builder.Finish();
+
+ superstructure::Goal::Builder superstructure_goal_builder =
+ builder.MakeBuilder<superstructure::Goal>();
+
+ superstructure_goal_builder.add_intake_front(intake_front_offset);
+ superstructure_goal_builder.add_intake_back(intake_back_offset);
+ superstructure_goal_builder.add_turret(turret_offset);
+ superstructure_goal_builder.add_climber(climber_offset);
+ superstructure_goal_builder.add_catapult(catapult_offset);
+ superstructure_goal_builder.add_fire(fire);
+
+ superstructure_goal_builder.add_roller_speed_front(roller_front_speed);
+ superstructure_goal_builder.add_roller_speed_back(roller_back_speed);
+ superstructure_goal_builder.add_roller_speed_compensation(
+ roller_speed_compensation ? 1.5 : 0.0f);
+
+ if (builder.Send(superstructure_goal_builder.Finish()) !=
+ aos::RawSender::Error::kOk) {
+ AOS_LOG(ERROR, "Sending superstructure goal failed.\n");
+ }
}
}
private:
+ double climber_pos_ = 0.0;
+
::aos::Sender<superstructure::Goal> superstructure_goal_sender_;
+ ::aos::Sender<frc971::control_loops::drivetrain::LocalizerControl>
+ localizer_control_sender_;
+
::aos::Fetcher<superstructure::Status> superstructure_status_fetcher_;
+
+ ::aos::Fetcher<Setpoint> setpoint_fetcher_;
};
} // namespace joysticks
diff --git a/y2022/localizer/BUILD b/y2022/localizer/BUILD
index e13159f..9e8c3d4 100644
--- a/y2022/localizer/BUILD
+++ b/y2022/localizer/BUILD
@@ -1,4 +1,4 @@
-load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
+load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library", "flatbuffer_ts_library")
load("//aos:flatbuffers.bzl", "cc_static_flatbuffer")
load("@npm//@bazel/typescript:index.bzl", "ts_library")
@@ -39,6 +39,30 @@
visibility = ["//visibility:public"],
)
+flatbuffer_cc_library(
+ name = "localizer_visualization_fbs",
+ srcs = ["localizer_visualization.fbs"],
+ gen_reflections = 1,
+ includes = [
+ ":localizer_status_fbs_includes",
+ "//frc971/control_loops:control_loops_fbs_includes",
+ "//frc971/control_loops/drivetrain:drivetrain_status_fbs_includes",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+flatbuffer_ts_library(
+ name = "localizer_visualization_ts_fbs",
+ srcs = ["localizer_visualization.fbs"],
+ includes = [
+ ":localizer_status_fbs_includes",
+ "//frc971/control_loops:control_loops_fbs_includes",
+ "//frc971/control_loops/drivetrain:drivetrain_status_fbs_includes",
+ ],
+ target_compatible_with = ["@platforms//os:linux"],
+ visibility = ["//visibility:public"],
+)
+
cc_static_flatbuffer(
name = "localizer_schema",
function = "frc971::controls::LocalizerStatusSchema",
@@ -54,8 +78,11 @@
deps = [
":localizer_output_fbs",
":localizer_status_fbs",
+ ":localizer_visualization_fbs",
"//aos/containers:ring_buffer",
+ "//aos/containers:sized_array",
"//aos/events:event_loop",
+ "//aos/network:message_bridge_server_fbs",
"//aos/time",
"//frc971/control_loops:c2d",
"//frc971/control_loops:control_loops_fbs",
@@ -67,8 +94,10 @@
"//frc971/wpilib:imu_fbs",
"//frc971/zeroing:imu_zeroer",
"//frc971/zeroing:wrap",
- "//y2020/vision/sift:sift_fbs",
"//y2022:constants",
+ "//y2022/control_loops/superstructure:superstructure_status_fbs",
+ "//y2022/vision:calibration_fbs",
+ "//y2022/vision:target_estimate_fbs",
"@org_tuxfamily_eigen//:eigen",
],
)
@@ -91,12 +120,14 @@
data = [
"//y2022:aos_config",
],
- shard_count = 10,
+ shard_count = 13,
deps = [
":localizer",
"//aos/events:simulated_event_loop",
+ "//aos/events/logging:log_writer",
"//aos/testing:googletest",
"//frc971/control_loops/drivetrain:drivetrain_test_lib",
+ "//y2022/control_loops/drivetrain:drivetrain_base",
],
)
diff --git a/y2022/localizer/localizer.cc b/y2022/localizer/localizer.cc
index 8d4f908..ea80e73 100644
--- a/y2022/localizer/localizer.cc
+++ b/y2022/localizer/localizer.cc
@@ -3,6 +3,7 @@
#include "frc971/control_loops/c2d.h"
#include "frc971/wpilib/imu_batch_generated.h"
#include "y2022/constants.h"
+#include "aos/json_to_flatbuffer.h"
namespace frc971::controls {
@@ -10,6 +11,11 @@
constexpr double kG = 9.80665;
constexpr std::chrono::microseconds kNominalDt(500);
+// Field position of the target (the 2022 target is conveniently in the middle
+// of the field....).
+constexpr double kVisionTargetX = 0.0;
+constexpr double kVisionTargetY = 0.0;
+
template <int N>
Eigen::Matrix<double, N, 1> MakeState(std::vector<double> values) {
CHECK_EQ(static_cast<size_t>(N), values.size());
@@ -29,6 +35,7 @@
.plant()
.coefficients()),
down_estimator_(dt_config) {
+ statistics_.rejection_counts.fill(0);
CHECK_EQ(branches_.capacity(), static_cast<size_t>(std::chrono::seconds(1) /
kNominalDt / kBranchPeriod));
if (dt_config_.is_simulated) {
@@ -77,10 +84,20 @@
B_continuous_accel_(kTheta, kThetaRate) = 1.0;
Q_continuous_model_.setZero();
- Q_continuous_model_.diagonal() << 1e-4, 1e-4, 1e-4, 1e-2, 1e-0, 1e-0, 1e-2,
+ Q_continuous_model_.diagonal() << 1e-2, 1e-2, 1e-8, 1e-2, 1e-0, 1e-0, 1e-2,
1e-0, 1e-0;
+ Q_continuous_accel_.setZero();
+ Q_continuous_accel_.diagonal() << 1e-2, 1e-2, 1e-20, 1e-4, 1e-4;
+
P_model_ = Q_continuous_model_ * aos::time::DurationInSeconds(kNominalDt);
+
+ // We can precalculate the discretizations of the accel model because it is
+ // actually LTI.
+
+ DiscretizeQAFast(Q_continuous_accel_, A_continuous_accel_, kNominalDt,
+ &Q_discrete_accel_, &A_discrete_accel_);
+ P_accel_ = Q_discrete_accel_;
}
Eigen::Matrix<double, ModelBasedLocalizer::kNModelStates,
@@ -281,6 +298,8 @@
&A_discrete);
P_model_ = A_discrete * P_model_ * A_discrete.transpose() + Q_discrete;
+ P_accel_ = A_discrete_accel_ * P_accel_ * A_discrete_accel_.transpose() +
+ Q_discrete_accel_;
Eigen::Matrix<double, kNModelOutputs, kNModelStates> H;
Eigen::Matrix<double, kNModelOutputs, kNModelOutputs> R;
@@ -300,8 +319,6 @@
if (branches_.empty()) {
VLOG(2) << "Initializing";
- current_state_.model_state.setZero();
- current_state_.accel_state.setZero();
current_state_.model_state(kLeftEncoder) = encoders(0);
current_state_.model_state(kRightEncoder) = encoders(1);
current_state_.branch_time = t;
@@ -404,6 +421,8 @@
++branch_counter_;
if (branch_counter_ % kBranchPeriod == 0) {
branches_.Push(new_branch);
+ old_positions_.Push(OldPosition{t, xytheta(), latest_turret_position_,
+ latest_turret_velocity_});
branch_counter_ = 0;
}
@@ -426,6 +445,241 @@
CHECK(std::isfinite(last_residual_));
}
+const ModelBasedLocalizer::OldPosition ModelBasedLocalizer::GetStateForTime(
+ aos::monotonic_clock::time_point time) {
+ if (old_positions_.empty()) {
+ return OldPosition{};
+ }
+
+ aos::monotonic_clock::duration lowest_time_error =
+ aos::monotonic_clock::duration::max();
+ const OldPosition *best_match = nullptr;
+ for (const OldPosition &sample : old_positions_) {
+ const aos::monotonic_clock::duration time_error =
+ std::chrono::abs(sample.sample_time - time);
+ if (time_error < lowest_time_error) {
+ lowest_time_error = time_error;
+ best_match = &sample;
+ }
+ }
+ return *best_match;
+}
+
+namespace {
+// Converts a flatbuffer TransformationMatrix to an Eigen matrix. Technically,
+// this should be able to do a single memcpy, but the extra verbosity here seems
+// appropriate.
+Eigen::Matrix<double, 4, 4> FlatbufferToTransformationMatrix(
+ const frc971::vision::calibration::TransformationMatrix &flatbuffer) {
+ CHECK_EQ(16u, CHECK_NOTNULL(flatbuffer.data())->size());
+ Eigen::Matrix<double, 4, 4> result;
+ result.setIdentity();
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ result(row, col) = (*flatbuffer.data())[row * 4 + col];
+ }
+ }
+ return result;
+}
+
+// Node names of the pis to listen for cameras from.
+const std::array<std::string_view, 4> kPisToUse{"pi1", "pi2", "pi3", "pi4"};
+}
+
+const Eigen::Matrix<double, 4, 4> ModelBasedLocalizer::CameraTransform(
+ const OldPosition &state,
+ const frc971::vision::calibration::CameraCalibration *calibration,
+ std::optional<RejectionReason> *rejection_reason) const {
+ CHECK_NOTNULL(rejection_reason);
+ CHECK_NOTNULL(calibration);
+ // Per the CameraCalibration specification, we can actually determine whether
+ // the camera is the turret camera just from the presence of the
+ // turret_extrinsics member.
+ const bool is_turret = calibration->has_turret_extrinsics();
+ // Ignore readings when the turret is spinning too fast, on the assumption
+ // that the odds of screwing up the time compensation are higher.
+ // Note that the current number here is chosen pretty arbitrarily--1 rad / sec
+ // seems reasonable, but may be unnecessarily low or high.
+ constexpr double kMaxTurretVelocity = 1.0;
+ if (is_turret && std::abs(state.turret_velocity) > kMaxTurretVelocity &&
+ !rejection_reason->has_value()) {
+ *rejection_reason = RejectionReason::TURRET_TOO_FAST;
+ }
+ CHECK(calibration->has_fixed_extrinsics());
+ const Eigen::Matrix<double, 4, 4> fixed_extrinsics =
+ FlatbufferToTransformationMatrix(*calibration->fixed_extrinsics());
+
+ // Calculate the pose of the camera relative to the robot origin.
+ Eigen::Matrix<double, 4, 4> H_robot_camera = fixed_extrinsics;
+ if (is_turret) {
+ H_robot_camera =
+ H_robot_camera *
+ frc971::control_loops::TransformationMatrixForYaw<double>(
+ state.turret_position) *
+ FlatbufferToTransformationMatrix(*calibration->turret_extrinsics());
+ }
+ return H_robot_camera;
+}
+
+const std::optional<Eigen::Vector2d>
+ModelBasedLocalizer::CameraMeasuredRobotPosition(
+ const OldPosition &state, const y2022::vision::TargetEstimate *target,
+ std::optional<RejectionReason> *rejection_reason,
+ Eigen::Matrix<double, 4, 4> *H_field_camera_measured) const {
+ if (!target->has_camera_calibration()) {
+ *rejection_reason = RejectionReason::NO_CALIBRATION;
+ return std::nullopt;
+ }
+ const Eigen::Matrix<double, 4, 4> H_robot_camera =
+ CameraTransform(state, target->camera_calibration(), rejection_reason);
+ const control_loops::Pose robot_pose(
+ {state.xytheta(0), state.xytheta(1), 0.0}, state.xytheta(2));
+ const Eigen::Matrix<double, 4, 4> H_field_robot =
+ robot_pose.AsTransformationMatrix();
+ // Current estimated pose of the camera in the global frame.
+ // Note that this is all really just an elaborate way of extracting the
+ // current estimated camera yaw, and nothing else.
+ const Eigen::Matrix<double, 4, 4> H_field_camera =
+ H_field_robot * H_robot_camera;
+ // Grab the implied yaw of the camera (the +Z axis is coming out of the front
+ // of the cameras).
+ const Eigen::Vector3d rotated_camera_z =
+ H_field_camera.block<3, 3>(0, 0) * Eigen::Vector3d(0, 0, 1);
+ const double camera_yaw =
+ std::atan2(rotated_camera_z.y(), rotated_camera_z.x());
+ // All right, now we need to use the heading and distance from the
+ // TargetEstimate, plus the yaw embedded in the camera_pose, to determine what
+ // the implied X/Y position of the robot is. To do this, we calculate the
+ // heading/distance from the target to the robot. The distance is easy, since
+ // that's the same as the distance from the robot to the target. The heading
+ // isn't too hard, but is obnoxious to think about, since the heading from the
+ // target to the robot is distinct from the heading from the robot to the
+ // target.
+
+ // Just to walk through examples to confirm that the below calculation is
+ // correct:
+ // * If yaw = 0, and angle_to_target = 0, we are at 180 deg relative to the
+ // target.
+ // * If yaw = 90 deg, and angle_to_target = 0, we are at -90 deg relative to
+ // the target.
+ // * If yaw = 0, and angle_to_target = 90 deg, we are at -90 deg relative to
+ // the target.
+ const double heading_from_target =
+ aos::math::NormalizeAngle(M_PI + camera_yaw + target->angle_to_target());
+ const double distance_from_target = target->distance();
+ // Extract the implied camera position on the field.
+ *H_field_camera_measured = H_field_camera;
+ // TODO(james): Are we going to need to evict the roll/pitch components of the
+ // camera extrinsics this year as well?
+ (*H_field_camera_measured)(0, 3) =
+ distance_from_target * std::cos(heading_from_target) + kVisionTargetX;
+ (*H_field_camera_measured)(1, 3) =
+ distance_from_target * std::sin(heading_from_target) + kVisionTargetY;
+ const Eigen::Matrix<double, 4, 4> H_field_robot_measured =
+ *H_field_camera_measured * H_robot_camera.inverse();
+ return H_field_robot_measured.block<2, 1>(0, 3);
+}
+
+void ModelBasedLocalizer::HandleImageMatch(
+ aos::monotonic_clock::time_point sample_time,
+ const y2022::vision::TargetEstimate *target, int camera_index) {
+ std::optional<RejectionReason> rejection_reason;
+
+ const OldPosition &state = GetStateForTime(sample_time);
+ Eigen::Matrix<double, 4, 4> H_field_camera_measured;
+ const std::optional<Eigen::Vector2d> measured_robot_position =
+ CameraMeasuredRobotPosition(state, target, &rejection_reason,
+ &H_field_camera_measured);
+ // Technically, rejection_reason should always be set if
+ // measured_robot_position is nullopt, but in the future we may have more
+ // recoverable rejection reasons that we wish to allow to propagate further
+ // into the process.
+ if (!measured_robot_position || rejection_reason.has_value()) {
+ CHECK(rejection_reason.has_value());
+ TallyRejection(rejection_reason.value());
+ return;
+ }
+
+ // Next, go through and do the actual Kalman corrections for the x/y
+ // measurement, for both the accel state and the model-based state.
+ const Eigen::Matrix<double, kNModelStates, kNModelStates> A_continuous_model =
+ AModel(current_state_.model_state);
+
+ Eigen::Matrix<double, kNModelStates, kNModelStates> A_discrete_model;
+ Eigen::Matrix<double, kNModelStates, kNModelStates> Q_discrete_model;
+
+ DiscretizeQAFast(Q_continuous_model_, A_continuous_model, kNominalDt,
+ &Q_discrete_model, &A_discrete_model);
+
+ Eigen::Matrix<double, 2, kNModelStates> H_model;
+ H_model.setZero();
+ Eigen::Matrix<double, 2, kNAccelStates> H_accel;
+ H_accel.setZero();
+ Eigen::Matrix<double, 2, 2> R;
+ R.setZero();
+ H_model(0, kX) = 1.0;
+ H_model(1, kY) = 1.0;
+ H_accel(0, kX) = 1.0;
+ H_accel(1, kY) = 1.0;
+ R.diagonal() << 1e-2, 1e-2;
+
+ const Eigen::Matrix<double, kNModelStates, 2> K_model =
+ P_model_ * H_model.transpose() *
+ (H_model * P_model_ * H_model.transpose() + R).inverse();
+ const Eigen::Matrix<double, kNAccelStates, 2> K_accel =
+ P_accel_ * H_accel.transpose() *
+ (H_accel * P_accel_ * H_accel.transpose() + R).inverse();
+ P_model_ = (Eigen::Matrix<double, kNModelStates, kNModelStates>::Identity() -
+ K_model * H_model) *
+ P_model_;
+ P_accel_ = (Eigen::Matrix<double, kNAccelStates, kNAccelStates>::Identity() -
+ K_accel * H_accel) *
+ P_accel_;
+ // And now we have to correct *everything* on all the branches:
+ for (CombinedState &state : branches_) {
+ state.model_state += K_model * (measured_robot_position.value() -
+ H_model * state.model_state);
+ state.accel_state += K_accel * (measured_robot_position.value() -
+ H_accel * state.accel_state);
+ }
+ current_state_.model_state +=
+ K_model *
+ (measured_robot_position.value() - H_model * current_state_.model_state);
+ current_state_.accel_state +=
+ K_accel *
+ (measured_robot_position.value() - H_accel * current_state_.accel_state);
+
+ statistics_.total_accepted++;
+ statistics_.total_candidates++;
+
+ const Eigen::Vector3d camera_z_in_field =
+ H_field_camera_measured.block<3, 3>(0, 0) * Eigen::Vector3d::UnitZ();
+ const double camera_yaw =
+ std::atan2(camera_z_in_field.y(), camera_z_in_field.x());
+
+ TargetEstimateDebugT debug;
+ debug.camera = static_cast<uint8_t>(camera_index);
+ debug.camera_x = H_field_camera_measured(0, 3);
+ debug.camera_y = H_field_camera_measured(1, 3);
+ debug.camera_theta = camera_yaw;
+ debug.implied_robot_x = measured_robot_position.value().x();
+ debug.implied_robot_y = measured_robot_position.value().y();
+ debug.implied_robot_theta = xytheta()(2);
+ debug.implied_turret_goal =
+ aos::math::NormalizeAngle(camera_yaw + target->angle_to_target());
+ debug.accepted = true;
+ debug.image_age_sec = aos::time::DurationInSeconds(t_ - sample_time);
+ image_debugs_.push_back(debug);
+}
+
+void ModelBasedLocalizer::HandleTurret(
+ aos::monotonic_clock::time_point sample_time, double turret_position,
+ double turret_velocity) {
+ last_turret_update_ = sample_time;
+ latest_turret_position_ = turret_position;
+ latest_turret_velocity_ = turret_velocity;
+}
+
void ModelBasedLocalizer::HandleReset(aos::monotonic_clock::time_point now,
const Eigen::Vector3d &xytheta) {
branches_.Reset();
@@ -468,8 +722,23 @@
return model_state_builder.Finish();
}
+flatbuffers::Offset<CumulativeStatistics>
+ModelBasedLocalizer::PopulateStatistics(flatbuffers::FlatBufferBuilder *fbb) {
+ const auto rejections_offset = fbb->CreateVector(
+ statistics_.rejection_counts.data(), statistics_.rejection_counts.size());
+
+ CumulativeStatistics::Builder stats_builder(*fbb);
+ stats_builder.add_total_accepted(statistics_.total_accepted);
+ stats_builder.add_total_candidates(statistics_.total_candidates);
+ stats_builder.add_rejection_reason_count(rejections_offset);
+ return stats_builder.Finish();
+}
+
flatbuffers::Offset<ModelBasedStatus> ModelBasedLocalizer::PopulateStatus(
flatbuffers::FlatBufferBuilder *fbb) {
+ const flatbuffers::Offset<CumulativeStatistics> stats_offset =
+ PopulateStatistics(fbb);
+
const flatbuffers::Offset<control_loops::drivetrain::DownEstimatorState>
down_estimator_offset = down_estimator_.PopulateStatus(fbb, t_);
@@ -508,9 +777,62 @@
builder.add_implied_accel_y(abs_accel_(1));
builder.add_implied_accel_z(abs_accel_(2));
builder.add_clock_resets(clock_resets_);
+ builder.add_statistics(stats_offset);
return builder.Finish();
}
+flatbuffers::Offset<LocalizerVisualization>
+ModelBasedLocalizer::PopulateVisualization(
+ flatbuffers::FlatBufferBuilder *fbb) {
+ const flatbuffers::Offset<CumulativeStatistics> stats_offset =
+ PopulateStatistics(fbb);
+
+ aos::SizedArray<flatbuffers::Offset<TargetEstimateDebug>, kDebugBufferSize>
+ debug_offsets;
+
+ for (const TargetEstimateDebugT& debug : image_debugs_) {
+ debug_offsets.push_back(PackTargetEstimateDebug(debug, fbb));
+ }
+
+ image_debugs_.clear();
+
+ const flatbuffers::Offset<
+ flatbuffers::Vector<flatbuffers::Offset<TargetEstimateDebug>>>
+ debug_offset =
+ fbb->CreateVector(debug_offsets.data(), debug_offsets.size());
+
+ LocalizerVisualization::Builder builder(*fbb);
+ builder.add_statistics(stats_offset);
+ builder.add_targets(debug_offset);
+ return builder.Finish();
+}
+
+void ModelBasedLocalizer::TallyRejection(const RejectionReason reason) {
+ statistics_.total_candidates++;
+ statistics_.rejection_counts[static_cast<size_t>(reason)]++;
+ TargetEstimateDebugT debug;
+ debug.accepted = false;
+ debug.rejection_reason = reason;
+ image_debugs_.push_back(debug);
+}
+
+flatbuffers::Offset<TargetEstimateDebug>
+ModelBasedLocalizer::PackTargetEstimateDebug(
+ const TargetEstimateDebugT &debug, flatbuffers::FlatBufferBuilder *fbb) {
+ if (!debug.accepted) {
+ TargetEstimateDebug::Builder builder(*fbb);
+ builder.add_accepted(debug.accepted);
+ builder.add_rejection_reason(debug.rejection_reason);
+ return builder.Finish();
+ } else {
+ flatbuffers::Offset<TargetEstimateDebug> offset =
+ TargetEstimateDebug::Pack(*fbb, &debug);
+ flatbuffers::GetMutableTemporaryPointer(*fbb, offset)
+ ->clear_rejection_reason();
+ return offset;
+ }
+}
+
namespace {
// Period at which the encoder readings from the IMU board wrap.
static double DrivetrainWrapPeriod() {
@@ -525,9 +847,14 @@
model_based_(dt_config),
status_sender_(event_loop_->MakeSender<LocalizerStatus>("/localizer")),
output_sender_(event_loop_->MakeSender<LocalizerOutput>("/localizer")),
+ visualization_sender_(
+ event_loop_->MakeSender<LocalizerVisualization>("/localizer")),
output_fetcher_(
event_loop_->MakeFetcher<frc971::control_loops::drivetrain::Output>(
"/drivetrain")),
+ clock_offset_fetcher_(
+ event_loop_->MakeFetcher<aos::message_bridge::ServerStatistics>(
+ "/aos")),
left_encoder_(-DrivetrainWrapPeriod() / 2.0, DrivetrainWrapPeriod()),
right_encoder_(-DrivetrainWrapPeriod() / 2.0, DrivetrainWrapPeriod()) {
event_loop_->MakeWatcher(
@@ -538,9 +865,48 @@
? model_based_.xytheta()(2)
: control.theta();
model_based_.HandleReset(event_loop_->monotonic_now(),
- {control.x(), control.y(), theta});
+ {control.x(), control.y(), theta});
});
event_loop_->MakeWatcher(
+ "/superstructure",
+ [this](const y2022::control_loops::superstructure::Status &status) {
+ if (!status.has_turret()) {
+ return;
+ }
+ CHECK(status.has_turret());
+ model_based_.HandleTurret(event_loop_->context().monotonic_event_time,
+ status.turret()->position(),
+ status.turret()->velocity());
+ });
+
+ for (size_t camera_index = 0; camera_index < kPisToUse.size(); ++camera_index) {
+ event_loop_->MakeWatcher(
+ absl::StrCat("/", kPisToUse[camera_index], "/camera"),
+ [this, camera_index](const y2022::vision::TargetEstimate &target) {
+ const std::optional<aos::monotonic_clock::duration> monotonic_offset =
+ ClockOffset(kPisToUse[camera_index]);
+ if (!monotonic_offset.has_value()) {
+ return;
+ }
+ // TODO(james): Get timestamp from message contents.
+ aos::monotonic_clock::time_point capture_time(
+ event_loop_->context().monotonic_remote_time - monotonic_offset.value());
+ if (capture_time > event_loop_->context().monotonic_event_time) {
+ model_based_.TallyRejection(RejectionReason::IMAGE_FROM_FUTURE);
+ return;
+ }
+ model_based_.HandleImageMatch(capture_time, &target, camera_index);
+ if (model_based_.NumQueuedImageDebugs() ==
+ ModelBasedLocalizer::kDebugBufferSize ||
+ (last_visualization_send_ + kMinVisualizationPeriod <
+ event_loop_->monotonic_now())) {
+ auto builder = visualization_sender_.MakeBuilder();
+ visualization_sender_.CheckOk(
+ builder.Send(model_based_.PopulateVisualization(builder.fbb())));
+ }
+ });
+ }
+ event_loop_->MakeWatcher(
"/localizer", [this](const frc971::IMUValuesBatch &values) {
CHECK(values.has_readings());
output_fetcher_.Fetch();
@@ -626,4 +992,30 @@
});
}
+std::optional<aos::monotonic_clock::duration> EventLoopLocalizer::ClockOffset(
+ std::string_view pi) {
+ std::optional<aos::monotonic_clock::duration> monotonic_offset;
+ clock_offset_fetcher_.Fetch();
+ if (clock_offset_fetcher_.get() != nullptr) {
+ for (const auto connection : *clock_offset_fetcher_->connections()) {
+ if (connection->has_node() && connection->node()->has_name() &&
+ connection->node()->name()->string_view() == pi) {
+ if (connection->has_monotonic_offset()) {
+ monotonic_offset =
+ std::chrono::nanoseconds(connection->monotonic_offset());
+ } else {
+ // If we don't have a monotonic offset, that means we aren't
+ // connected.
+ model_based_.TallyRejection(
+ RejectionReason::MESSAGE_BRIDGE_DISCONNECTED);
+ return std::nullopt;
+ }
+ break;
+ }
+ }
+ }
+ CHECK(monotonic_offset.has_value());
+ return monotonic_offset;
+}
+
} // namespace frc971::controls
diff --git a/y2022/localizer/localizer.h b/y2022/localizer/localizer.h
index d7b6a23..4b7eff0 100644
--- a/y2022/localizer/localizer.h
+++ b/y2022/localizer/localizer.h
@@ -3,18 +3,21 @@
#include "Eigen/Dense"
#include "Eigen/Geometry"
-
-#include "aos/events/event_loop.h"
#include "aos/containers/ring_buffer.h"
+#include "aos/containers/sized_array.h"
+#include "aos/events/event_loop.h"
+#include "aos/network/message_bridge_server_generated.h"
#include "aos/time/time.h"
-#include "y2020/vision/sift/sift_generated.h"
-#include "y2022/localizer/localizer_status_generated.h"
-#include "y2022/localizer/localizer_output_generated.h"
-#include "frc971/control_loops/drivetrain/improved_down_estimator.h"
#include "frc971/control_loops/drivetrain/drivetrain_output_generated.h"
+#include "frc971/control_loops/drivetrain/improved_down_estimator.h"
#include "frc971/control_loops/drivetrain/localizer_generated.h"
#include "frc971/zeroing/imu_zeroer.h"
#include "frc971/zeroing/wrap.h"
+#include "y2022/control_loops/superstructure/superstructure_status_generated.h"
+#include "y2022/localizer/localizer_output_generated.h"
+#include "y2022/localizer/localizer_status_generated.h"
+#include "y2022/localizer/localizer_visualization_generated.h"
+#include "y2022/vision/target_estimate_generated.h"
namespace frc971::controls {
@@ -92,7 +95,9 @@
// Branching period, in cycles.
// Needs 10 to even stay alive, and still at ~96% CPU.
// ~20 gives ~55-60% CPU.
- static constexpr int kBranchPeriod = 20;
+ static constexpr int kBranchPeriod = 100;
+
+ static constexpr size_t kDebugBufferSize = 10;
typedef Eigen::Matrix<double, kNModelStates, 1> ModelState;
typedef Eigen::Matrix<double, kNAccelStates, 1> AccelState;
@@ -104,10 +109,11 @@
void HandleImu(aos::monotonic_clock::time_point t,
const Eigen::Vector3d &gyro, const Eigen::Vector3d &accel,
const Eigen::Vector2d encoders, const Eigen::Vector2d voltage);
- void HandleImageMatch(aos::monotonic_clock::time_point,
- const vision::sift::ImageMatchResult *) {
- LOG(FATAL) << "Unimplemented.";
- }
+ void HandleTurret(aos::monotonic_clock::time_point sample_time,
+ double turret_position, double turret_velocity);
+ void HandleImageMatch(aos::monotonic_clock::time_point sample_time,
+ const y2022::vision::TargetEstimate *target,
+ int camera_index);
void HandleReset(aos::monotonic_clock::time_point,
const Eigen::Vector3d &xytheta);
@@ -128,12 +134,30 @@
void set_longitudinal_offset(double offset) { long_offset_ = offset; }
+ void TallyRejection(const RejectionReason reason);
+
+ flatbuffers::Offset<LocalizerVisualization> PopulateVisualization(
+ flatbuffers::FlatBufferBuilder *fbb);
+
+ size_t NumQueuedImageDebugs() const { return image_debugs_.size(); }
+
private:
struct CombinedState {
- AccelState accel_state;
- ModelState model_state;
- aos::monotonic_clock::time_point branch_time;
- double accumulated_divergence;
+ AccelState accel_state = AccelState::Zero();
+ ModelState model_state = ModelState::Zero();
+ aos::monotonic_clock::time_point branch_time =
+ aos::monotonic_clock::min_time;
+ double accumulated_divergence = 0.0;
+ };
+
+ // Struct to store state data needed to perform a camera correction, since
+ // camera corrections require looking back in time.
+ struct OldPosition {
+ aos::monotonic_clock::time_point sample_time =
+ aos::monotonic_clock::min_time;
+ Eigen::Vector3d xytheta = Eigen::Vector3d::Zero();
+ double turret_position = 0.0;
+ double turret_velocity = 0.0;
};
static flatbuffers::Offset<AccelBasedState> BuildAccelState(
@@ -169,22 +193,53 @@
const AccelInput &accel_input, const ModelInput &model_input,
aos::monotonic_clock::duration dt);
+ const OldPosition GetStateForTime(aos::monotonic_clock::time_point time);
+
+ // Returns the transformation to get from the camera frame to the robot frame
+ // for the specified state.
+ const Eigen::Matrix<double, 4, 4> CameraTransform(
+ const OldPosition &state,
+ const frc971::vision::calibration::CameraCalibration *calibration,
+ std::optional<RejectionReason> *rejection_reason) const;
+
+ // Returns the robot x/y position implied by the specified camera data and
+ // estimated state from that time.
+ // H_field_camera is passed in so that it can be used as a debugging output.
+ const std::optional<Eigen::Vector2d> CameraMeasuredRobotPosition(
+ const OldPosition &state, const y2022::vision::TargetEstimate *target,
+ std::optional<RejectionReason> *rejection_reason,
+ Eigen::Matrix<double, 4, 4> *H_field_camera_measured) const;
+
+ flatbuffers::Offset<TargetEstimateDebug> PackTargetEstimateDebug(
+ const TargetEstimateDebugT &debug, flatbuffers::FlatBufferBuilder *fbb);
+
+ flatbuffers::Offset<CumulativeStatistics> PopulateStatistics(
+ flatbuffers::FlatBufferBuilder *fbb);
+
const control_loops::drivetrain::DrivetrainConfig<double> dt_config_;
const StateFeedbackHybridPlantCoefficients<2, 2, 2, double>
velocity_drivetrain_coefficients_;
Eigen::Matrix<double, kNModelStates, kNModelStates> A_continuous_model_;
Eigen::Matrix<double, kNAccelStates, kNAccelStates> A_continuous_accel_;
+ Eigen::Matrix<double, kNAccelStates, kNAccelStates> A_discrete_accel_;
Eigen::Matrix<double, kNModelStates, kNModelInputs> B_continuous_model_;
Eigen::Matrix<double, kNAccelStates, kNAccelInputs> B_continuous_accel_;
Eigen::Matrix<double, kNModelStates, kNModelStates> Q_continuous_model_;
Eigen::Matrix<double, kNModelStates, kNModelStates> P_model_;
+
+ Eigen::Matrix<double, kNAccelStates, kNAccelStates> Q_continuous_accel_;
+ Eigen::Matrix<double, kNAccelStates, kNAccelStates> Q_discrete_accel_;
+
+ Eigen::Matrix<double, kNAccelStates, kNAccelStates> P_accel_;
+
+ control_loops::drivetrain::DrivetrainUkf down_estimator_;
+
// When we are following the model, we will, on each iteration:
// 1) Perform a model-based update of a single state.
// 2) Add a hypothetical non-model-based entry based on the current state.
// 3) Evict too-old non-model-based entries.
- control_loops::drivetrain::DrivetrainUkf down_estimator_;
// Buffer of old branches these are all created by initializing a new
// model-based state based on the current state, and then initializing a new
@@ -195,6 +250,10 @@
aos::RingBuffer<CombinedState, 2000 / kBranchPeriod> branches_;
int branch_counter_ = 0;
+ // Buffer of old x/y/theta positions. This is used so that we can have a
+ // reference for exactly where we thought a camera was when it took an image.
+ aos::RingBuffer<OldPosition, 500 / kBranchPeriod> old_positions_;
+
CombinedState current_state_;
aos::monotonic_clock::time_point t_ = aos::monotonic_clock::min_time;
bool using_model_;
@@ -215,11 +274,38 @@
int clock_resets_ = 0;
+ std::optional<aos::monotonic_clock::time_point> last_turret_update_;
+ double latest_turret_position_ = 0.0;
+ double latest_turret_velocity_ = 0.0;
+
+ // Stuff to track faults.
+ static constexpr size_t kNumRejectionReasons =
+ static_cast<int>(RejectionReason::MAX) -
+ static_cast<int>(RejectionReason::MIN) + 1;
+
+ struct Statistics {
+ int total_accepted = 0;
+ int total_candidates = 0;
+ static_assert(0 == static_cast<int>(RejectionReason::MIN));
+ static_assert(
+ kNumRejectionReasons ==
+ sizeof(
+ std::invoke_result<decltype(EnumValuesRejectionReason)>::type) /
+ sizeof(RejectionReason),
+ "RejectionReason has non-contiguous error values.");
+ std::array<int, kNumRejectionReasons> rejection_counts;
+ };
+ Statistics statistics_;
+
+ aos::SizedArray<TargetEstimateDebugT, kDebugBufferSize> image_debugs_;
+
friend class testing::LocalizerTest;
};
class EventLoopLocalizer {
public:
+ static constexpr std::chrono::milliseconds kMinVisualizationPeriod{100};
+
EventLoopLocalizer(
aos::EventLoop *event_loop,
const control_loops::drivetrain::DrivetrainConfig<double> &dt_config);
@@ -227,14 +313,20 @@
ModelBasedLocalizer *localizer() { return &model_based_; }
private:
+ std::optional<aos::monotonic_clock::duration> ClockOffset(
+ std::string_view pi);
aos::EventLoop *event_loop_;
ModelBasedLocalizer model_based_;
aos::Sender<LocalizerStatus> status_sender_;
aos::Sender<LocalizerOutput> output_sender_;
+ aos::Sender<LocalizerVisualization> visualization_sender_;
aos::Fetcher<frc971::control_loops::drivetrain::Output> output_fetcher_;
+ aos::Fetcher<aos::message_bridge::ServerStatistics> clock_offset_fetcher_;
zeroing::ImuZeroer zeroer_;
aos::monotonic_clock::time_point last_output_send_ =
aos::monotonic_clock::min_time;
+ aos::monotonic_clock::time_point last_visualization_send_ =
+ aos::monotonic_clock::min_time;
std::optional<aos::monotonic_clock::time_point> last_pico_timestamp_;
aos::monotonic_clock::duration pico_offset_error_;
// t = pico_offset_ + pico_timestamp.
diff --git a/y2022/localizer/localizer_status.fbs b/y2022/localizer/localizer_status.fbs
index 80cee0b..8be770e 100644
--- a/y2022/localizer/localizer_status.fbs
+++ b/y2022/localizer/localizer_status.fbs
@@ -2,6 +2,20 @@
namespace frc971.controls;
+enum RejectionReason : byte {
+ IMAGE_FROM_FUTURE = 0,
+ NO_CALIBRATION = 1,
+ TURRET_TOO_FAST = 2,
+ MESSAGE_BRIDGE_DISCONNECTED = 3,
+}
+
+table CumulativeStatistics {
+ total_accepted:int (id: 0);
+ total_candidates:int (id: 1);
+ // Indexed by integer value of RejectionReason enum.
+ rejection_reason_count:[int] (id: 2);
+}
+
// Stores the state associated with the acceleration-based modelling.
table AccelBasedState {
// x/y position, in meters.
@@ -74,6 +88,7 @@
// Number of times we have missed an IMU reading. Should never increase except
// *maybe* during startup.
clock_resets:int (id: 17);
+ statistics:CumulativeStatistics (id: 18);
}
table LocalizerStatus {
diff --git a/y2022/localizer/localizer_test.cc b/y2022/localizer/localizer_test.cc
index 1997b80..58df869 100644
--- a/y2022/localizer/localizer_test.cc
+++ b/y2022/localizer/localizer_test.cc
@@ -1,14 +1,31 @@
#include "y2022/localizer/localizer.h"
+#include "aos/events/logging/log_writer.h"
#include "aos/events/simulated_event_loop.h"
#include "gtest/gtest.h"
#include "frc971/control_loops/drivetrain/drivetrain_test_lib.h"
+#include "frc971/control_loops/pose.h"
+#include "y2022/vision/target_estimate_generated.h"
+#include "y2022/control_loops/superstructure/superstructure_status_generated.h"
+#include "y2022/control_loops/drivetrain/drivetrain_base.h"
+
+DEFINE_string(output_folder, "",
+ "If set, logs all channels to the provided logfile.");
namespace frc971::controls::testing {
typedef ModelBasedLocalizer::ModelState ModelState;
typedef ModelBasedLocalizer::AccelState AccelState;
typedef ModelBasedLocalizer::ModelInput ModelInput;
typedef ModelBasedLocalizer::AccelInput AccelInput;
+
+using frc971::vision::calibration::CameraCalibrationT;
+using frc971::vision::calibration::TransformationMatrixT;
+using frc971::control_loops::drivetrain::DrivetrainConfig;
+using frc971::control_loops::drivetrain::LocalizerControl;
+using frc971::control_loops::Pose;
+using y2022::vision::TargetEstimate;
+using y2022::vision::TargetEstimateT;
+
namespace {
constexpr size_t kX = ModelBasedLocalizer::kX;
constexpr size_t kY = ModelBasedLocalizer::kY;
@@ -26,13 +43,52 @@
constexpr size_t kRightVoltageError = ModelBasedLocalizer::kRightVoltageError;
constexpr size_t kLeftVoltage = ModelBasedLocalizer::kLeftVoltage;
constexpr size_t kRightVoltage = ModelBasedLocalizer::kRightVoltage;
+
+Eigen::Matrix<double, 4, 4> TurretRobotTransformation() {
+ Eigen::Matrix<double, 4, 4> H;
+ H.setIdentity();
+ H.block<3, 1>(0, 3) << 1, 1.1, 0.9;
+ return H;
+}
+
+// Provides the location of the camera on the turret.
+Eigen::Matrix<double, 4, 4> CameraTurretTransformation() {
+ Eigen::Matrix<double, 4, 4> H;
+ H.setIdentity();
+ H.block<3, 1>(0, 3) << 0.1, 0, 0;
+ H.block<3, 3>(0, 0) << 0, 0, 1, -1, 0, 0, 0, -1, 0;
+
+ // Introduce a bit of pitch to make sure that we're exercising all the code.
+ H.block<3, 3>(0, 0) =
+ Eigen::AngleAxis<double>(0.1, Eigen::Vector3d::UnitY()) *
+ H.block<3, 3>(0, 0);
+ return H;
+}
+
+// Copies an Eigen matrix into a row-major vector of the data.
+std::vector<float> MatrixToVector(const Eigen::Matrix<double, 4, 4> &H) {
+ std::vector<float> data;
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ data.push_back(H(row, col));
+ }
+ }
+ return data;
+}
+
+DrivetrainConfig<double> GetTest2022DrivetrainConfig() {
+ DrivetrainConfig<double> config =
+ y2022::control_loops::drivetrain::GetDrivetrainConfig();
+ config.is_simulated = true;
+ return config;
+}
}
class LocalizerTest : public ::testing::Test {
protected:
LocalizerTest()
: dt_config_(
- control_loops::drivetrain::testing::GetTestDrivetrainConfig()),
+ GetTest2022DrivetrainConfig()),
localizer_(dt_config_) {
localizer_.set_longitudinal_offset(0.0);
}
@@ -177,7 +233,7 @@
const Eigen::Vector2d encoders{0.0, 0.0};
const Eigen::Vector2d voltages{0.0, 0.0};
Eigen::Vector3d accel{5.0, 2.0, 9.80665};
- Eigen::Vector3d accel_gs = accel / 9.80665;
+ Eigen::Vector3d accel_gs = dt_config_.imu_transform.inverse() * accel / 9.80665;
while (t < start) {
// Spin to fill up the buffer.
localizer_.HandleImu(t, gyro, Eigen::Vector3d::UnitZ(), encoders, voltages);
@@ -215,7 +271,7 @@
// and then leave them constant, which should make it look like we are going
// around in a circle.
accel = Eigen::Vector3d{-accel(1), accel(0), 9.80665};
- accel_gs = accel / 9.80665;
+ accel_gs = dt_config_.imu_transform.inverse() * accel / 9.80665;
// v^2 / r = a
// w * r = v
// v^2 / v * w = a
@@ -292,6 +348,8 @@
aos::configuration::GetNode(&configuration_.message(), "roborio")),
imu_node_(
aos::configuration::GetNode(&configuration_.message(), "imu")),
+ camera_node_(
+ aos::configuration::GetNode(&configuration_.message(), "pi1")),
dt_config_(
control_loops::drivetrain::testing::GetTestDrivetrainConfig()),
localizer_event_loop_(
@@ -308,37 +366,177 @@
event_loop_factory_.MakeEventLoop("test", roborio_node_)),
imu_test_event_loop_(
event_loop_factory_.MakeEventLoop("test", imu_node_)),
+ camera_test_event_loop_(
+ event_loop_factory_.MakeEventLoop("test", camera_node_)),
logger_test_event_loop_(
event_loop_factory_.GetNodeEventLoopFactory("logger")
->MakeEventLoop("test")),
output_sender_(
roborio_test_event_loop_->MakeSender<Output>("/drivetrain")),
+ turret_sender_(
+ roborio_test_event_loop_
+ ->MakeSender<y2022::control_loops::superstructure::Status>(
+ "/superstructure")),
+ target_sender_(
+ camera_test_event_loop_->MakeSender<y2022::vision::TargetEstimate>(
+ "/camera")),
+ control_sender_(roborio_test_event_loop_->MakeSender<LocalizerControl>(
+ "/drivetrain")),
output_fetcher_(roborio_test_event_loop_->MakeFetcher<LocalizerOutput>(
"/localizer")),
status_fetcher_(
imu_test_event_loop_->MakeFetcher<LocalizerStatus>("/localizer")) {
localizer_.localizer()->set_longitudinal_offset(0.0);
- aos::TimerHandler *timer = roborio_test_event_loop_->AddTimer([this]() {
- auto builder = output_sender_.MakeBuilder();
- auto output_builder = builder.MakeBuilder<Output>();
- output_builder.add_left_voltage(output_voltages_(0));
- output_builder.add_right_voltage(output_voltages_(1));
- builder.CheckOk(builder.Send(output_builder.Finish()));
- });
- roborio_test_event_loop_->OnRun([timer, this]() {
- timer->Setup(roborio_test_event_loop_->monotonic_now(),
- std::chrono::milliseconds(5));
- });
+ {
+ aos::TimerHandler *timer = roborio_test_event_loop_->AddTimer([this]() {
+ {
+ auto builder = output_sender_.MakeBuilder();
+ auto output_builder = builder.MakeBuilder<Output>();
+ output_builder.add_left_voltage(output_voltages_(0));
+ output_builder.add_right_voltage(output_voltages_(1));
+ builder.CheckOk(builder.Send(output_builder.Finish()));
+ }
+ {
+ auto builder = turret_sender_.MakeBuilder();
+ auto turret_builder =
+ builder
+ .MakeBuilder<frc971::control_loops::
+ PotAndAbsoluteEncoderProfiledJointStatus>();
+ turret_builder.add_position(turret_position_);
+ turret_builder.add_velocity(turret_velocity_);
+ const auto turret_offset = turret_builder.Finish();
+ auto status_builder =
+ builder
+ .MakeBuilder<y2022::control_loops::superstructure::Status>();
+ status_builder.add_turret(turret_offset);
+ builder.CheckOk(builder.Send(status_builder.Finish()));
+ }
+ });
+ roborio_test_event_loop_->OnRun([timer, this]() {
+ timer->Setup(roborio_test_event_loop_->monotonic_now(),
+ std::chrono::milliseconds(5));
+ });
+ }
+ {
+ aos::TimerHandler *timer = camera_test_event_loop_->AddTimer([this]() {
+ if (!send_targets_) {
+ return;
+ }
+ const frc971::control_loops::Pose robot_pose(
+ {drivetrain_plant_.GetPosition().x(),
+ drivetrain_plant_.GetPosition().y(), 0.0},
+ drivetrain_plant_.state()(2, 0));
+ const Eigen::Matrix<double, 4, 4> H_turret_camera =
+ frc971::control_loops::TransformationMatrixForYaw(
+ turret_position_) *
+ CameraTurretTransformation();
+
+ const Eigen::Matrix<double, 4, 4> H_field_camera =
+ robot_pose.AsTransformationMatrix() * TurretRobotTransformation() *
+ H_turret_camera;
+ const Eigen::Matrix<double, 4, 4> target_transform =
+ Eigen::Matrix<double, 4, 4>::Identity();
+ const Eigen::Matrix<double, 4, 4> H_camera_target =
+ H_field_camera.inverse() * target_transform;
+ const Eigen::Matrix<double, 4, 4> H_target_camera =
+ H_camera_target.inverse();
+
+ std::unique_ptr<y2022::vision::TargetEstimateT> estimate(
+ new y2022::vision::TargetEstimateT());
+ estimate->distance = H_target_camera.block<2, 1>(0, 3).norm();
+ estimate->angle_to_target =
+ std::atan2(-H_camera_target(0, 3), H_camera_target(2, 3));
+ estimate->camera_calibration.reset(new CameraCalibrationT());
+ {
+ estimate->camera_calibration->fixed_extrinsics.reset(
+ new TransformationMatrixT());
+ TransformationMatrixT *H_robot_turret =
+ estimate->camera_calibration->fixed_extrinsics.get();
+ H_robot_turret->data = MatrixToVector(TurretRobotTransformation());
+ }
+
+ estimate->camera_calibration->turret_extrinsics.reset(
+ new TransformationMatrixT());
+ estimate->camera_calibration->turret_extrinsics->data =
+ MatrixToVector(CameraTurretTransformation());
+
+ auto builder = target_sender_.MakeBuilder();
+ builder.CheckOk(
+ builder.Send(TargetEstimate::Pack(*builder.fbb(), estimate.get())));
+ });
+ camera_test_event_loop_->OnRun([timer, this]() {
+ timer->Setup(camera_test_event_loop_->monotonic_now(),
+ std::chrono::milliseconds(50));
+ });
+ }
+
+ localizer_control_send_timer_ =
+ roborio_test_event_loop_->AddTimer([this]() {
+ auto builder = control_sender_.MakeBuilder();
+ auto control_builder = builder.MakeBuilder<LocalizerControl>();
+ control_builder.add_x(localizer_control_x_);
+ control_builder.add_y(localizer_control_y_);
+ control_builder.add_theta(localizer_control_theta_);
+ control_builder.add_theta_uncertainty(0.01);
+ control_builder.add_keep_current_theta(false);
+ builder.CheckOk(builder.Send(control_builder.Finish()));
+ });
+
// Get things zeroed.
event_loop_factory_.RunFor(std::chrono::seconds(10));
CHECK(status_fetcher_.Fetch());
CHECK(status_fetcher_->zeroed());
+
+ if (!FLAGS_output_folder.empty()) {
+ logger_event_loop_ =
+ event_loop_factory_.MakeEventLoop("logger", imu_node_);
+ logger_ = std::make_unique<aos::logger::Logger>(logger_event_loop_.get());
+ logger_->StartLoggingOnRun(FLAGS_output_folder);
+ }
+ }
+
+ void SendLocalizerControl(double x, double y, double theta) {
+ localizer_control_x_ = x;
+ localizer_control_y_ = y;
+ localizer_control_theta_ = theta;
+ localizer_control_send_timer_->Setup(
+ roborio_test_event_loop_->monotonic_now());
+ }
+ ::testing::AssertionResult IsNear(double expected, double actual,
+ double epsilon) {
+ if (std::abs(expected - actual) < epsilon) {
+ return ::testing::AssertionSuccess();
+ } else {
+ return ::testing::AssertionFailure()
+ << "Expected " << expected << " but got " << actual
+ << " with a max difference of " << epsilon
+ << " and an actual difference of " << std::abs(expected - actual);
+ }
+ }
+ ::testing::AssertionResult VerifyEstimatorAccurate(double eps) {
+ const Eigen::Matrix<double, 5, 1> true_state = drivetrain_plant_.state();
+ ::testing::AssertionResult result(true);
+ status_fetcher_.Fetch();
+ if (!(result = IsNear(status_fetcher_->model_based()->x(), true_state(0),
+ eps))) {
+ return result;
+ }
+ if (!(result = IsNear(status_fetcher_->model_based()->y(), true_state(1),
+ eps))) {
+ return result;
+ }
+ if (!(result = IsNear(status_fetcher_->model_based()->theta(),
+ true_state(2), eps))) {
+ return result;
+ }
+ return result;
}
aos::FlatbufferDetachedBuffer<aos::Configuration> configuration_;
aos::SimulatedEventLoopFactory event_loop_factory_;
const aos::Node *const roborio_node_;
const aos::Node *const imu_node_;
+ const aos::Node *const camera_node_;
const control_loops::drivetrain::DrivetrainConfig<double> dt_config_;
std::unique_ptr<aos::EventLoop> localizer_event_loop_;
EventLoopLocalizer localizer_;
@@ -349,13 +547,30 @@
std::unique_ptr<aos::EventLoop> roborio_test_event_loop_;
std::unique_ptr<aos::EventLoop> imu_test_event_loop_;
+ std::unique_ptr<aos::EventLoop> camera_test_event_loop_;
std::unique_ptr<aos::EventLoop> logger_test_event_loop_;
aos::Sender<Output> output_sender_;
+ aos::Sender<y2022::control_loops::superstructure::Status> turret_sender_;
+ aos::Sender<y2022::vision::TargetEstimate> target_sender_;
+ aos::Sender<LocalizerControl> control_sender_;
aos::Fetcher<LocalizerOutput> output_fetcher_;
aos::Fetcher<LocalizerStatus> status_fetcher_;
Eigen::Vector2d output_voltages_ = Eigen::Vector2d::Zero();
+
+ aos::TimerHandler *localizer_control_send_timer_;
+
+ bool send_targets_ = false;
+ double turret_position_ = 0.0;
+ double turret_velocity_ = 0.0;
+
+ double localizer_control_x_ = 0.0;
+ double localizer_control_y_ = 0.0;
+ double localizer_control_theta_ = 0.0;
+
+ std::unique_ptr<aos::EventLoop> logger_event_loop_;
+ std::unique_ptr<aos::logger::Logger> logger_;
};
TEST_F(EventLoopLocalizerTest, Nominal) {
@@ -525,4 +740,79 @@
status_fetcher_->model_based()->y(), 1e-6);
}
+// Tests that image corrections in the nominal case (no errors) causes no
+// issues.
+TEST_F(EventLoopLocalizerTest, NominalImageCorrections) {
+ output_voltages_ << 3.0, 2.0;
+ drivetrain_plant_.set_accel_sin_magnitude(0.01);
+ send_targets_ = true;
+
+ event_loop_factory_.RunFor(std::chrono::seconds(4));
+ CHECK(status_fetcher_.Fetch());
+ ASSERT_TRUE(status_fetcher_->model_based()->using_model());
+ EXPECT_TRUE(VerifyEstimatorAccurate(1e-1));
+ ASSERT_TRUE(status_fetcher_->model_based()->has_statistics());
+ ASSERT_LT(10,
+ status_fetcher_->model_based()->statistics()->total_candidates());
+ ASSERT_EQ(status_fetcher_->model_based()->statistics()->total_candidates(),
+ status_fetcher_->model_based()->statistics()->total_accepted());
+}
+
+// Tests that image corrections when there is an error at the start results
+// in us actually getting corrected over time.
+TEST_F(EventLoopLocalizerTest, ImageCorrections) {
+ output_voltages_ << 0.0, 0.0;
+ drivetrain_plant_.mutable_state()->x() = 2.0;
+ drivetrain_plant_.mutable_state()->y() = 2.0;
+ SendLocalizerControl(5.0, 3.0, 0.0);
+ event_loop_factory_.RunFor(std::chrono::seconds(4));
+ CHECK(output_fetcher_.Fetch());
+ ASSERT_NEAR(5.0, output_fetcher_->x(), 1e-5);
+ ASSERT_NEAR(3.0, output_fetcher_->y(), 1e-5);
+ ASSERT_NEAR(0.0, output_fetcher_->theta(), 1e-5);
+
+ send_targets_ = true;
+
+ event_loop_factory_.RunFor(std::chrono::seconds(4));
+ CHECK(status_fetcher_.Fetch());
+ ASSERT_TRUE(status_fetcher_->model_based()->using_model());
+ EXPECT_TRUE(VerifyEstimatorAccurate(1e-1));
+ ASSERT_TRUE(status_fetcher_->model_based()->has_statistics());
+ ASSERT_LT(10,
+ status_fetcher_->model_based()->statistics()->total_candidates());
+ ASSERT_EQ(status_fetcher_->model_based()->statistics()->total_candidates(),
+ status_fetcher_->model_based()->statistics()->total_accepted());
+}
+
+// Tests that image corrections when we are in accel mode works.
+TEST_F(EventLoopLocalizerTest, ImageCorrectionsInAccel) {
+ output_voltages_ << 0.0, 0.0;
+ drivetrain_plant_.set_left_voltage_offset(200.0);
+ drivetrain_plant_.set_right_voltage_offset(200.0);
+ drivetrain_plant_.set_accel_sin_magnitude(0.01);
+ drivetrain_plant_.mutable_state()->x() = 2.0;
+ drivetrain_plant_.mutable_state()->y() = 2.0;
+ SendLocalizerControl(5.0, 3.0, 0.0);
+ event_loop_factory_.RunFor(std::chrono::seconds(1));
+ CHECK(output_fetcher_.Fetch());
+ CHECK(status_fetcher_.Fetch());
+ ASSERT_FALSE(status_fetcher_->model_based()->using_model());
+ EXPECT_FALSE(VerifyEstimatorAccurate(0.5));
+
+ send_targets_ = true;
+
+ event_loop_factory_.RunFor(std::chrono::seconds(4));
+ CHECK(status_fetcher_.Fetch());
+ ASSERT_FALSE(status_fetcher_->model_based()->using_model());
+ EXPECT_TRUE(VerifyEstimatorAccurate(0.5));
+ // y should be noticeably more accurate than x, since we are just driving
+ // straight.
+ ASSERT_NEAR(drivetrain_plant_.state()(1), status_fetcher_->model_based()->y(), 0.1);
+ ASSERT_TRUE(status_fetcher_->model_based()->has_statistics());
+ ASSERT_LT(10,
+ status_fetcher_->model_based()->statistics()->total_candidates());
+ ASSERT_EQ(status_fetcher_->model_based()->statistics()->total_candidates(),
+ status_fetcher_->model_based()->statistics()->total_accepted());
+}
+
} // namespace frc91::controls::testing
diff --git a/y2022/localizer/localizer_visualization.fbs b/y2022/localizer/localizer_visualization.fbs
new file mode 100644
index 0000000..6cca9e8
--- /dev/null
+++ b/y2022/localizer/localizer_visualization.fbs
@@ -0,0 +1,26 @@
+include "y2022/localizer/localizer_status.fbs";
+
+namespace frc971.controls;
+
+table TargetEstimateDebug {
+ camera:uint8 (id: 0);
+ camera_x:double (id: 1);
+ camera_y:double (id: 2);
+ camera_theta:double (id: 3);
+ implied_robot_x:double (id: 4);
+ implied_robot_y:double (id: 5);
+ implied_robot_theta:double (id: 6);
+ implied_turret_goal:double (id: 7);
+ accepted:bool (id: 8);
+ rejection_reason:RejectionReason (id: 9);
+ // Image age (more human-readable than trying to interpret raw nanosecond
+ // values).
+ image_age_sec:double (id: 10);
+}
+
+table LocalizerVisualization {
+ targets:[TargetEstimateDebug] (id: 0);
+ statistics:CumulativeStatistics (id: 1);
+}
+
+root_type LocalizerVisualization;
diff --git a/y2022/setpoint.fbs b/y2022/setpoint.fbs
new file mode 100644
index 0000000..f8dc458
--- /dev/null
+++ b/y2022/setpoint.fbs
@@ -0,0 +1,14 @@
+namespace y2022.input.joysticks;
+
+// Table for dynamically setting shooter goals
+table Setpoint {
+ // Catapult shot release angle
+ catapult_position:double (id: 0);
+ // Catapult shot velocity
+ catapult_velocity:double (id: 1);
+
+ // Turret angle
+ turret:double (id: 2);
+}
+
+root_type Setpoint;
diff --git a/y2022/setpoint_setter.cc b/y2022/setpoint_setter.cc
new file mode 100644
index 0000000..9a77ec8
--- /dev/null
+++ b/y2022/setpoint_setter.cc
@@ -0,0 +1,38 @@
+#include "aos/events/shm_event_loop.h"
+#include "aos/init.h"
+#include "gflags/gflags.h"
+#include "glog/logging.h"
+#include "y2022/constants.h"
+#include "y2022/setpoint_generated.h"
+
+DEFINE_double(catapult_position,
+ y2022::constants::Values::kDefaultCatapultShotPosition(),
+ "Catapult shot position");
+DEFINE_double(catapult_velocity,
+ y2022::constants::Values::kDefaultCatapultShotVelocity(),
+ "Catapult shot velocity");
+DEFINE_double(turret, 0.0, "Turret setpoint");
+
+using y2022::input::joysticks::Setpoint;
+
+int main(int argc, char **argv) {
+ aos::InitGoogle(&argc, &argv);
+
+ aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+ aos::configuration::ReadConfig("config.json");
+
+ aos::ShmEventLoop event_loop(&config.message());
+
+ auto setpoint_sender = event_loop.MakeSender<Setpoint>("/superstructure");
+
+ aos::Sender<Setpoint>::Builder builder = setpoint_sender.MakeBuilder();
+
+ Setpoint::Builder setpoint_builder = builder.MakeBuilder<Setpoint>();
+
+ setpoint_builder.add_catapult_position(FLAGS_catapult_position);
+ setpoint_builder.add_catapult_velocity(FLAGS_catapult_velocity);
+ setpoint_builder.add_turret(FLAGS_turret);
+ builder.CheckOk(builder.Send(setpoint_builder.Finish()));
+
+ return 0;
+}
diff --git a/y2022/vision/calib_files/calibration_pi-9971-1_cam-22-07_2022-02-16_21-20-00.000000000.json b/y2022/vision/calib_files/calibration_pi-9971-1_cam-22-07_2022-02-16_21-20-00.000000000.json
index 27ed863..35efa45 100755
--- a/y2022/vision/calib_files/calibration_pi-9971-1_cam-22-07_2022-02-16_21-20-00.000000000.json
+++ b/y2022/vision/calib_files/calibration_pi-9971-1_cam-22-07_2022-02-16_21-20-00.000000000.json
@@ -1,6 +1,6 @@
{
"node_name": "pi1",
- "team_number": 971,
+ "team_number": 9971,
"intrinsics": [
388.062378,
0.0,
diff --git a/y2022/wpilib_interface.cc b/y2022/wpilib_interface.cc
index eb70b6f..24f8323 100644
--- a/y2022/wpilib_interface.cc
+++ b/y2022/wpilib_interface.cc
@@ -141,6 +141,13 @@
UpdateMediumEncoderFilterHz(kMaxMediumEncoderPulsesPerSecond);
}
+ void Start() override {
+ // TODO(Ravago): Figure out why adding multiple DMA readers results in weird
+ // behavior
+ // AddToDMA(&imu_heading_reader_);
+ AddToDMA(&imu_yaw_rate_reader_);
+ }
+
// Auto mode switches.
void set_autonomous_mode(int i, ::std::unique_ptr<frc::DigitalInput> sensor) {
autonomous_modes_.at(i) = ::std::move(sensor);
@@ -162,11 +169,13 @@
}
void set_heading_input(::std::unique_ptr<frc::DigitalInput> sensor) {
- imu_heading_reader_.set_input(::std::move(sensor));
+ imu_heading_input_ = ::std::move(sensor);
+ imu_heading_reader_.set_input(imu_heading_input_.get());
}
void set_yaw_rate_input(::std::unique_ptr<frc::DigitalInput> sensor) {
- imu_yaw_rate_reader_.set_input(::std::move(sensor));
+ imu_yaw_rate_input_ = ::std::move(sensor);
+ imu_yaw_rate_reader_.set_input(imu_yaw_rate_input_.get());
}
void RunIteration() override {
@@ -177,7 +186,7 @@
CopyPosition(catapult_encoder_, &catapult,
Values::kCatapultEncoderCountsPerRevolution(),
Values::kCatapultEncoderRatio(), catapult_pot_translate,
- true, values_->catapult.potentiometer_offset);
+ false, values_->catapult.potentiometer_offset);
flatbuffers::Offset<frc971::PotAndAbsolutePosition> catapult_offset =
frc971::PotAndAbsolutePosition::Pack(*builder.fbb(), &catapult);
@@ -201,12 +210,13 @@
frc971::PotAndAbsolutePositionT intake_front;
CopyPosition(intake_encoder_front_, &intake_front,
Values::kIntakeEncoderCountsPerRevolution(),
- Values::kIntakeEncoderRatio(), intake_pot_translate, false,
+ Values::kIntakeEncoderRatio(), intake_pot_translate, true,
values_->intake_front.potentiometer_offset);
frc971::PotAndAbsolutePositionT intake_back;
CopyPosition(intake_encoder_back_, &intake_back,
Values::kIntakeEncoderCountsPerRevolution(),
- Values::kIntakeEncoderRatio(), intake_pot_translate, false,
+ Values::kIntakeEncoderRatio(),
+ intake_pot_translate, true,
values_->intake_back.potentiometer_offset);
frc971::PotAndAbsolutePositionT turret;
CopyPosition(turret_encoder_, &turret,
@@ -272,14 +282,19 @@
constexpr double kScaledRangeLow = 0.1;
constexpr double kScaledRangeHigh = 0.9;
+ constexpr double kPWMFrequencyHz = 200;
+ double heading_duty_cycle =
+ imu_heading_reader_.last_width() * kPWMFrequencyHz;
+ double velocity_duty_cycle =
+ imu_yaw_rate_reader_.last_width() * kPWMFrequencyHz;
+
constexpr double kDutyCycleScale =
1 / (kScaledRangeHigh - kScaledRangeLow);
-
// scale from 0.1 - 0.9 to 0 - 1
double rescaled_heading_duty_cycle =
- (imu_heading_reader_.Read() - kScaledRangeLow) * kDutyCycleScale;
+ (heading_duty_cycle - kScaledRangeLow) * kDutyCycleScale;
double rescaled_velocity_duty_cycle =
- (imu_yaw_rate_reader_.Read() - kScaledRangeLow) * kDutyCycleScale;
+ (velocity_duty_cycle - kScaledRangeLow) * kDutyCycleScale;
if (!std::isnan(rescaled_heading_duty_cycle)) {
gyro_reading_builder.add_angle(rescaled_heading_duty_cycle *
@@ -393,14 +408,15 @@
std::array<std::unique_ptr<frc::DigitalInput>, 2> autonomous_modes_;
std::unique_ptr<frc::DigitalInput> intake_beambreak_front_,
- intake_beambreak_back_, turret_beambreak_;
+ intake_beambreak_back_, turret_beambreak_, imu_heading_input_,
+ imu_yaw_rate_input_;
std::unique_ptr<frc::AnalogInput> climber_potentiometer_,
flipper_arm_right_potentiometer_, flipper_arm_left_potentiometer_;
frc971::wpilib::AbsoluteEncoderAndPotentiometer intake_encoder_front_,
intake_encoder_back_, turret_encoder_, catapult_encoder_;
- frc971::wpilib::DutyCycleReader imu_heading_reader_, imu_yaw_rate_reader_;
+ frc971::wpilib::DMAPulseWidthReader imu_heading_reader_, imu_yaw_rate_reader_;
};
class SuperstructureWriter
@@ -422,10 +438,6 @@
catapult_falcon_1_ = ::std::move(t);
}
- void set_catapult_falcon_2(::std::unique_ptr<::frc::TalonFX> t) {
- catapult_falcon_2_ = ::std::move(t);
- }
-
void set_intake_falcon_front(::std::unique_ptr<frc::TalonFX> t) {
intake_falcon_front_ = ::std::move(t);
}
@@ -490,7 +502,6 @@
intake_falcon_back_->SetDisabled();
transfer_roller_victor_->SetDisabled();
catapult_falcon_1_->SetDisabled();
- catapult_falcon_2_->SetDisabled();
turret_falcon_->SetDisabled();
}
@@ -503,12 +514,11 @@
WriteCan(output.roller_voltage_back(), roller_falcon_back_.get());
WritePwm(output.transfer_roller_voltage(), transfer_roller_victor_.get());
- WriteCan(output.flipper_arms_voltage(), flipper_arms_falcon_.get());
+ WriteCan(-output.flipper_arms_voltage(), flipper_arms_falcon_.get());
WritePwm(output.catapult_voltage(), catapult_falcon_1_.get());
- WritePwm(output.catapult_voltage(), catapult_falcon_2_.get());
- WritePwm(output.turret_voltage(), turret_falcon_.get());
+ WritePwm(-output.turret_voltage(), turret_falcon_.get());
}
static void WriteCan(const double voltage,
@@ -533,7 +543,7 @@
flipper_arms_falcon_;
::std::unique_ptr<::frc::TalonFX> turret_falcon_, catapult_falcon_1_,
- catapult_falcon_2_, climber_falcon_;
+ climber_falcon_;
::std::unique_ptr<::frc::VictorSP> transfer_roller_victor_;
};
@@ -604,50 +614,52 @@
// Thread 2.
::aos::ShmEventLoop pdp_fetcher_event_loop(&config.message());
::frc971::wpilib::PDPFetcher pdp_fetcher(&pdp_fetcher_event_loop);
- AddLoop(&pdp_fetcher_event_loop);
+ ;AddLoop(&pdp_fetcher_event_loop);
// Thread 3.
::aos::ShmEventLoop sensor_reader_event_loop(&config.message());
SensorReader sensor_reader(&sensor_reader_event_loop, values);
- sensor_reader.set_drivetrain_left_encoder(make_encoder(0));
- sensor_reader.set_drivetrain_right_encoder(make_encoder(1));
+ sensor_reader.set_drivetrain_left_encoder(make_encoder(1));
+ sensor_reader.set_drivetrain_right_encoder(make_encoder(0));
- sensor_reader.set_intake_encoder_front(make_encoder(2));
+ sensor_reader.set_intake_encoder_front(make_encoder(3));
sensor_reader.set_intake_front_absolute_pwm(
- make_unique<frc::DigitalInput>(2));
- sensor_reader.set_intake_front_potentiometer(
- make_unique<frc::AnalogInput>(2));
-
- sensor_reader.set_intake_encoder_back(make_encoder(3));
- sensor_reader.set_intake_back_absolute_pwm(
make_unique<frc::DigitalInput>(3));
- sensor_reader.set_intake_back_potentiometer(
+ sensor_reader.set_intake_front_potentiometer(
make_unique<frc::AnalogInput>(3));
- sensor_reader.set_turret_encoder(make_encoder(4));
- sensor_reader.set_turret_absolute_pwm(make_unique<frc::DigitalInput>(4));
- sensor_reader.set_turret_potentiometer(make_unique<frc::AnalogInput>(4));
+ sensor_reader.set_intake_encoder_back(make_encoder(4));
+ sensor_reader.set_intake_back_absolute_pwm(
+ make_unique<frc::DigitalInput>(4));
+ sensor_reader.set_intake_back_potentiometer(
+ make_unique<frc::AnalogInput>(4));
- sensor_reader.set_intake_beambreak_front(make_unique<frc::DigitalInput>(5));
- sensor_reader.set_intake_beambreak_back(make_unique<frc::DigitalInput>(6));
+ sensor_reader.set_turret_encoder(make_encoder(5));
+ sensor_reader.set_turret_absolute_pwm(make_unique<frc::DigitalInput>(5));
+ sensor_reader.set_turret_potentiometer(make_unique<frc::AnalogInput>(5));
+
+ // TODO(milind): correct intake beambreak ports once set
+ sensor_reader.set_intake_beambreak_front(
+ make_unique<frc::DigitalInput>(22));
+ sensor_reader.set_intake_beambreak_back(make_unique<frc::DigitalInput>(23));
sensor_reader.set_turret_beambreak(make_unique<frc::DigitalInput>(7));
- sensor_reader.set_climber_potentiometer(make_unique<frc::AnalogInput>(5));
+ sensor_reader.set_climber_potentiometer(make_unique<frc::AnalogInput>(7));
sensor_reader.set_flipper_arm_left_potentiometer(
- make_unique<frc::AnalogInput>(4));
+ make_unique<frc::AnalogInput>(0));
sensor_reader.set_flipper_arm_right_potentiometer(
- make_unique<frc::AnalogInput>(5));
+ make_unique<frc::AnalogInput>(1));
- sensor_reader.set_catapult_encoder(
- make_unique<frc::Encoder>(0, 1, false, frc::Encoder::k4X));
+ // TODO(milind): correct catapult encoder and absolute pwm ports
+ sensor_reader.set_catapult_encoder(make_encoder(2));
sensor_reader.set_catapult_absolute_pwm(
std::make_unique<frc::DigitalInput>(2));
sensor_reader.set_catapult_potentiometer(
std::make_unique<frc::AnalogInput>(2));
- sensor_reader.set_heading_input(make_unique<frc::DigitalInput>(8));
- sensor_reader.set_yaw_rate_input(make_unique<frc::DigitalInput>(9));
+ sensor_reader.set_heading_input(make_unique<frc::DigitalInput>(9));
+ sensor_reader.set_yaw_rate_input(make_unique<frc::DigitalInput>(8));
AddLoop(&sensor_reader_event_loop);
@@ -655,27 +667,29 @@
::aos::ShmEventLoop output_event_loop(&config.message());
::frc971::wpilib::DrivetrainWriter drivetrain_writer(&output_event_loop);
drivetrain_writer.set_left_controller0(
- ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(1)), true);
+ ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(1)), false);
drivetrain_writer.set_right_controller0(
- ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(0)), false);
+ ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(0)), true);
SuperstructureWriter superstructure_writer(&output_event_loop);
- superstructure_writer.set_turret_falcon(make_unique<::frc::TalonFX>(8));
+ superstructure_writer.set_turret_falcon(make_unique<::frc::TalonFX>(3));
superstructure_writer.set_roller_falcon_front(
- make_unique<::ctre::phoenix::motorcontrol::can::TalonFX>(3));
+ make_unique<::ctre::phoenix::motorcontrol::can::TalonFX>(0));
superstructure_writer.set_roller_falcon_back(
- make_unique<::ctre::phoenix::motorcontrol::can::TalonFX>(4));
- superstructure_writer.set_transfer_roller_victor(
- make_unique<::frc::VictorSP>(9));
- superstructure_writer.set_intake_falcon_front(make_unique<frc::TalonFX>(5));
- superstructure_writer.set_intake_falcon_back(make_unique<frc::TalonFX>(6));
- superstructure_writer.set_climber_falcon(make_unique<frc::TalonFX>(7));
- superstructure_writer.set_flipper_arms_falcon(
- make_unique<::ctre::phoenix::motorcontrol::can::TalonFX>(5));
+ make_unique<::ctre::phoenix::motorcontrol::can::TalonFX>(1));
- superstructure_writer.set_catapult_falcon_1(make_unique<::frc::TalonFX>(2));
- superstructure_writer.set_catapult_falcon_2(make_unique<::frc::TalonFX>(3));
+ // TODO(milind): correct port
+ superstructure_writer.set_transfer_roller_victor(
+ make_unique<::frc::VictorSP>(5));
+
+ superstructure_writer.set_intake_falcon_front(make_unique<frc::TalonFX>(2));
+ superstructure_writer.set_intake_falcon_back(make_unique<frc::TalonFX>(4));
+ superstructure_writer.set_climber_falcon(make_unique<frc::TalonFX>(8));
+ superstructure_writer.set_flipper_arms_falcon(
+ make_unique<::ctre::phoenix::motorcontrol::can::TalonFX>(2));
+
+ superstructure_writer.set_catapult_falcon_1(make_unique<::frc::TalonFX>(9));
AddLoop(&output_event_loop);
diff --git a/y2022/y2022_imu.json b/y2022/y2022_imu.json
index 35f1ab0..3d97c3c 100644
--- a/y2022/y2022_imu.json
+++ b/y2022/y2022_imu.json
@@ -193,6 +193,10 @@
"name": "/roborio/aos",
"type": "aos.starter.Status",
"source_node": "roborio",
+ "logger": "LOCAL_AND_REMOTE_LOGGER",
+ "logger_nodes": [
+ "imu"
+ ],
"destination_nodes": [
{
"name": "imu",
@@ -222,7 +226,7 @@
"max_size": 2000,
"logger": "LOCAL_AND_REMOTE_LOGGER",
"logger_nodes": [
- "roborio"
+ "logger"
],
"destination_nodes": [
{
@@ -247,13 +251,45 @@
},
{
"name": "/localizer",
+ "type": "frc971.controls.LocalizerVisualization",
+ "source_node": "imu",
+ "frequency": 200,
+ "max_size": 2000,
+ "logger": "LOCAL_AND_REMOTE_LOGGER",
+ "logger_nodes": [
+ "logger"
+ ],
+ "destination_nodes": [
+ {
+ "name": "logger",
+ "priority": 5,
+ "timestamp_logger": "LOCAL_AND_REMOTE_LOGGER",
+ "timestamp_logger_nodes": [
+ "imu"
+ ],
+ "time_to_live": 5000000
+ }
+ ]
+ },
+ {
+ "name": "/imu/aos/remote_timestamps/logger/localizer/frc971-controls-LocalizerVisualization",
+ "type": "aos.message_bridge.RemoteMessage",
+ "source_node": "imu",
+ "logger": "NOT_LOGGED",
+ "frequency": 200,
+ "num_senders": 2,
+ "max_size": 200
+ },
+ {
+ "name": "/localizer",
"type": "frc971.controls.LocalizerOutput",
"source_node": "imu",
"frequency": 200,
"max_size": 200,
"logger": "LOCAL_AND_REMOTE_LOGGER",
"logger_nodes": [
- "roborio"
+ "roborio",
+ "logger"
],
"destination_nodes": [
{
@@ -337,9 +373,7 @@
},
{
"name": "localizer",
- "executable_name": "localizer",
- "autostart": false,
- "autorestart": false,
+ "executable_name": "localizer_main",
"nodes": [
"imu"
]
@@ -361,9 +395,9 @@
{
"name": "localizer_logger",
"executable_name": "logger_main",
- "args": ["--logging_folder", "", "--snappy_compress"],
+ "args": ["--snappy_compress"],
"nodes": [
- "logger"
+ "imu"
]
},
{
diff --git a/y2022/y2022_logger.json b/y2022/y2022_logger.json
index 6b879cf..2407b9e 100644
--- a/y2022/y2022_logger.json
+++ b/y2022/y2022_logger.json
@@ -189,6 +189,11 @@
"frequency": 15,
"num_senders": 2,
"max_size": 400,
+ "logger": "LOCAL_AND_REMOTE_LOGGER",
+ "logger_nodes": [
+ "roborio",
+ "imu"
+ ],
"destination_nodes": [
{
"name": "pi1",
diff --git a/y2022/y2022_pi_template.json b/y2022/y2022_pi_template.json
index c2e35cc..7f49e41 100644
--- a/y2022/y2022_pi_template.json
+++ b/y2022/y2022_pi_template.json
@@ -75,7 +75,8 @@
"num_senders": 2,
"logger": "LOCAL_AND_REMOTE_LOGGER",
"logger_nodes": [
- "roborio"
+ "roborio",
+ "imu"
],
"max_size": 200,
"destination_nodes": [
diff --git a/y2022/y2022_roborio.json b/y2022/y2022_roborio.json
index f3bf5d0..b16f0cb 100644
--- a/y2022/y2022_roborio.json
+++ b/y2022/y2022_roborio.json
@@ -246,6 +246,12 @@
"max_size": 72
},
{
+ "name": "/superstructure",
+ "type": "y2022.input.joysticks.Setpoint",
+ "source_node": "roborio",
+ "num_senders": 2
+ },
+ {
"name": "/drivetrain",
"type": "frc971.sensors.GyroReading",
"source_node": "roborio",
diff --git a/yarn.lock b/yarn.lock
index 207757e..e76092f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,53 +2,53 @@
# yarn lockfile v1
-"@angular-devkit/architect@0.1301.4":
- version "0.1301.4"
- resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1301.4.tgz#2fc51bcae0dcb581c8be401e2fde7bbd10b43076"
- integrity sha512-p6G8CEMnE+gYwxRyEttj3QGsuNJ3Kusi7iwBIzWyf2RpJSdGzXdwUEiRGg6iS0YHFr06/ZFfAWfnM2DQvNm4TA==
+"@angular-devkit/architect@0.1302.0":
+ version "0.1302.0"
+ resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1302.0.tgz#31a2e6f0c744c5076c85b6db71e31665d7daef55"
+ integrity sha512-1CmVYvxyfvK/khTcDJwwXibm/z4upM2j5SDpwuIdaLx21E4oQPmHn+U/quT/jE5VI1zfZi2vfvIaSXn9XQzMiQ==
dependencies:
- "@angular-devkit/core" "13.1.4"
+ "@angular-devkit/core" "13.2.0"
rxjs "6.6.7"
-"@angular-devkit/core@13.1.4":
- version "13.1.4"
- resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-13.1.4.tgz#b5b6ddd674ae351f83beff2e4a0d702096bdfd47"
- integrity sha512-225Gjy4iVxh5Jo9njJnaG75M/Dt95UW+dEPCGWKV5E/++7UUlXlo9sNWq8x2vJm2nhtsPkpnXNOt4pW1mIDwqQ==
+"@angular-devkit/core@13.2.0":
+ version "13.2.0"
+ resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-13.2.0.tgz#d7ee99ba40af70193a436a27ee1591a1ec754cd9"
+ integrity sha512-5+aV2W2QUazySMKusBuT2pi2qsXWpTHJG2x62mKGAy0lxzwG8l3if+WP3Uh85SQS+zqlHeKxEbmm9zNn8ZrzFg==
dependencies:
- ajv "8.8.2"
+ ajv "8.9.0"
ajv-formats "2.1.1"
fast-json-stable-stringify "2.1.0"
magic-string "0.25.7"
rxjs "6.6.7"
source-map "0.7.3"
-"@angular-devkit/schematics@13.1.4":
- version "13.1.4"
- resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-13.1.4.tgz#e8ed817887aa51268dec27d8d6188e2f3f10742a"
- integrity sha512-yBa7IeC4cLZ7s137NAQD+sMB5c6SI6UJ6xYxl6J/CvV2RLGOZZA93i4GuRALi5s82eLi1fH+HEL/gvf3JQynzQ==
+"@angular-devkit/schematics@13.2.0":
+ version "13.2.0"
+ resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-13.2.0.tgz#656a5491be9f25e08faffd410c6ad9a75a82a8a2"
+ integrity sha512-EwoqDqLJH5YpWiLuQJwonnJu2bi4xQlyKXyUTuXsQ4gIsAPrg+ijyAe+F/brAtDLBj0sU7JHoC0U1yx2pZ7f1A==
dependencies:
- "@angular-devkit/core" "13.1.4"
+ "@angular-devkit/core" "13.2.0"
jsonc-parser "3.0.0"
magic-string "0.25.7"
ora "5.4.1"
rxjs "6.6.7"
-"@angular/animations@latest":
- version "13.1.3"
- resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-13.1.3.tgz#2da6ad99602bfb450624a7499d6f81366c3a4519"
- integrity sha512-OwsVQsNHubIgRcxnjti4CU3QJnqd7Z2b+2iu3M349Oxyqxz4DNCqKXalDuJZt/b0yNfirvYO3kCgBfj4PF43QQ==
+"@angular/animations@13.2.0":
+ version "13.2.0"
+ resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-13.2.0.tgz#001983463ea5a1b0ffc8e86b0cd5efeb3acb3a4d"
+ integrity sha512-zLmNxkfxDQShJ97V9gTyQdlEbCD/zDUdpHXKlUViBIbe2M13FLGV3e2D+x9jGr/PRzFe0cukOnYxNEHJqqjqPA==
dependencies:
tslib "^2.3.0"
-"@angular/cli@latest":
- version "13.1.4"
- resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-13.1.4.tgz#34e6e87d1c6950408167c41293cf2cd5d1e00a2e"
- integrity sha512-PP9xpvDDCHhLTIZjewQQzzf+JbpF2s5mXTW2AgIL/E53ukaVvXwwjFMt9dQvECwut/LDpThoc3OfqcGrmwtqnA==
+"@angular/cli@13.2.0":
+ version "13.2.0"
+ resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-13.2.0.tgz#550841330a4eead75466f423c68a57be3640ec53"
+ integrity sha512-xrtClCucVSBwELG6zgaHrjC71p1rZOkwjF/HewnOFNjyjXSbWIO2y5d/6O2wxmNASoeStpiEU0zPpwDGhXiYpQ==
dependencies:
- "@angular-devkit/architect" "0.1301.4"
- "@angular-devkit/core" "13.1.4"
- "@angular-devkit/schematics" "13.1.4"
- "@schematics/angular" "13.1.4"
+ "@angular-devkit/architect" "0.1302.0"
+ "@angular-devkit/core" "13.2.0"
+ "@angular-devkit/schematics" "13.2.0"
+ "@schematics/angular" "13.2.0"
"@yarnpkg/lockfile" "1.1.0"
ansi-colors "4.1.1"
debug "4.3.3"
@@ -59,23 +59,23 @@
npm-pick-manifest "6.1.1"
open "8.4.0"
ora "5.4.1"
- pacote "12.0.2"
- resolve "1.20.0"
+ pacote "12.0.3"
+ resolve "1.22.0"
semver "7.3.5"
symbol-observable "4.0.0"
uuid "8.3.2"
-"@angular/common@latest":
- version "13.1.3"
- resolved "https://registry.yarnpkg.com/@angular/common/-/common-13.1.3.tgz#4c80f45cfd00a17543559c5fbebe0a7a7cf403ed"
- integrity sha512-8qf5syeXUogf3+GSu6IRJjrk46UKh9L0QuLx+OSIl/df0y1ewx7e28q3BAUEEnOnKrLzpPNxWs2iwModc4KYfg==
+"@angular/common@13.2.0":
+ version "13.2.0"
+ resolved "https://registry.yarnpkg.com/@angular/common/-/common-13.2.0.tgz#d5e311c14c90867d5da7d1d5f539813e338a7d5f"
+ integrity sha512-zyq3kscl5BoY+xxl4YOfbKP72xwzx/vKLE+2ougjPu2spm5KIllIAo/VrxVqIBrsGWT/4gs9pvIOqOdOfufxUA==
dependencies:
tslib "^2.3.0"
-"@angular/compiler-cli@latest":
- version "13.1.3"
- resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-13.1.3.tgz#0269370350e928f22f3150523f95bc490a1e7a7a"
- integrity sha512-ALURaJATc54DzPuiZBvALf/alEp1wr7Hjmw4FuMn2cU7p8lwKkra1Dz5dAZOxh7jAcD1GJfrK/+Sb7A3cuuKjQ==
+"@angular/compiler-cli@13.2.0":
+ version "13.2.0"
+ resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-13.2.0.tgz#6eee613e86ec028a4a2b88a9dce45512eef7e862"
+ integrity sha512-IDX0X3GXjhUzd/cFyNZBG3eVqh6Y2W7MYvH9tXbZHcJ6vH9RkN2+zh/XQautVWy4EP33oQoDlsydfYKqbHr9TA==
dependencies:
"@babel/core" "^7.8.6"
canonical-path "1.0.0"
@@ -89,24 +89,31 @@
tslib "^2.3.0"
yargs "^17.2.1"
-"@angular/compiler@latest":
- version "13.1.3"
- resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-13.1.3.tgz#fc33b06046599ecc943f55049e0a121d5ab46d4f"
- integrity sha512-dbHs/Oa+Dn+7i0jKtlVDE0lD0DaUC+lVzAcTK/zS37LrckrTMn1CA+z9bZ4gpHig9RU0wgV3YORxv0wokyiB8A==
+"@angular/compiler@13.2.0":
+ version "13.2.0"
+ resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-13.2.0.tgz#4112970f2bf6e347511de1e32459d717141750e3"
+ integrity sha512-TTA+Mn31vAwI4qiaH0h8DqNV3DWgZF+Q9G8Qqbw17k8Jf+B5CdLkMYBF8wbGegIdsEfo+6DebCp71W+aJxuSlw==
dependencies:
tslib "^2.3.0"
-"@angular/core@latest":
- version "13.1.3"
- resolved "https://registry.yarnpkg.com/@angular/core/-/core-13.1.3.tgz#4afd71f674f9ead1aada81315f84846cdba10fa4"
- integrity sha512-rvCnIAonRx7VnH2Mv9lQR+UYdlFQQetZCjPw8QOswOspEpHpEPDrp1HxDIqJnHxNqW0n8J3Zev/VgQYr0481UA==
+"@angular/core@13.2.0":
+ version "13.2.0"
+ resolved "https://registry.yarnpkg.com/@angular/core/-/core-13.2.0.tgz#8db7b6f56eb2f211b72d943582061b247f39fe7f"
+ integrity sha512-mWRWbbZ6k00AicA/GrxmWKaw8upo77sRQz4tSYKpwVKt2TtCeoW8OkdYUpnmuVjxpF0bD6PtVc0e1fD6es/ElA==
dependencies:
tslib "^2.3.0"
-"@angular/platform-browser@latest":
- version "13.1.3"
- resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-13.1.3.tgz#69d90b10e89e11f14f5798d1b6fd788255a6114e"
- integrity sha512-mnWjdr9UTNZvGk8jPI6O9FIhun8Q/0ghy3dg3I9AfRzEG4vPiIZW1ICksTiB+jV9etzhKpidtmg71bwgeXax1A==
+"@angular/forms@13.2.0":
+ version "13.2.0"
+ resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-13.2.0.tgz#67d505c09175d1ba809be721303316db7b0c60d4"
+ integrity sha512-aduXLuvqynDRRdb316yY1O5rdMQ2DKeNxu5P2FG1nkLQ3hqZvpiaUMhFyXvKDG3s0rV5e/PZs1cpg0Aqdfwevw==
+ dependencies:
+ tslib "^2.3.0"
+
+"@angular/platform-browser@13.2.0":
+ version "13.2.0"
+ resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-13.2.0.tgz#d8a309c231dec646ab1dad28240466a00151b54b"
+ integrity sha512-FB9eKdRqpjopTFbea5JXnqSPFR7DZD4nepOSGnYttV9cVj4pABqx2A6FJCnyvPPUSTamODye/pNkGmzP2P1gcw==
dependencies:
tslib "^2.3.0"
@@ -351,26 +358,31 @@
"@babel/helper-validator-identifier" "^7.16.7"
to-fast-properties "^2.0.0"
-"@bazel/concatjs@latest":
- version "4.6.1"
- resolved "https://registry.yarnpkg.com/@bazel/concatjs/-/concatjs-4.6.1.tgz#c40abc3fbe362cbad1e3383c4e78b58d1f4c8e13"
- integrity sha512-eI79oS1F8vK9kw8ttg/zeQYyOiN9FfhJjYyammkc3q4WlNs3Xm717Cp/CquSwPyFh022mB00Tib4gHJ7zp+VpA==
+"@bazel/concatjs@4.4.6":
+ version "4.4.6"
+ resolved "https://registry.yarnpkg.com/@bazel/concatjs/-/concatjs-4.4.6.tgz#842e4472f5d766a610a93ecc1315dd89a17f0cd3"
+ integrity sha512-2qt6M9G5S3gPTTB/VG8KwhTtv5w9ZqedFvOQS7yBbHHyV4UEWSxijhqHinpbJs0iKOWRbsDGE+jtRdgq8Vu+ZQ==
dependencies:
protobufjs "6.8.8"
source-map-support "0.5.9"
tsutils "3.21.0"
-"@bazel/rollup@latest":
- version "4.6.1"
- resolved "https://registry.yarnpkg.com/@bazel/rollup/-/rollup-4.6.1.tgz#7e5054b1b43c1052bdd8824d9f1a11a410d540e2"
- integrity sha512-8a2halG0dnzjs0BgGiHOM47LVCotGW0I9lSWLdwrTxTNOp8fEdbZ8C7TMHFE+8Zc3Z5oerqR8uvIpMarOJQumQ==
- dependencies:
- "@bazel/worker" "4.6.1"
+"@bazel/protractor@4.4.6":
+ version "4.4.6"
+ resolved "https://registry.yarnpkg.com/@bazel/protractor/-/protractor-4.4.6.tgz#2ed9c3780caf741bbe6e6947bcb84635fe0aa2a1"
+ integrity sha512-jLg2FDf7pCx87P56+HFEdXmcACpHJiGvePnVhKohLs0QOj+SEi1hDz4YgUsTBmcxZOEftI/v0zmXwgi9FFZ8QA==
-"@bazel/terser@latest":
- version "4.6.1"
- resolved "https://registry.yarnpkg.com/@bazel/terser/-/terser-4.6.1.tgz#a3f70672cef7b9383b42930691d6fc8be4b8d993"
- integrity sha512-LOXNSLCscyiNDxhLEgIL+Unj7UQpH6s+IkujizRpEyMrVVrhun5do972ab4TdqCXi9rxQKBBkgj8EL43gMimwg==
+"@bazel/rollup@4.4.6":
+ version "4.4.6"
+ resolved "https://registry.yarnpkg.com/@bazel/rollup/-/rollup-4.4.6.tgz#936d34c9c8159d42f84f1ac3c9ebb1bed27f691a"
+ integrity sha512-VujfM6QGuNpQZVzOf2nfAi3Xoi4EdA9nXXy6Gq4WiSaDPbgZrlXl/4Db+Hb6Nej5uvWqqppgvigCPHcWX9yM/w==
+ dependencies:
+ "@bazel/worker" "4.4.6"
+
+"@bazel/terser@4.4.6":
+ version "4.4.6"
+ resolved "https://registry.yarnpkg.com/@bazel/terser/-/terser-4.4.6.tgz#7e1579078ab604a0b53135f43086c0a060c83804"
+ integrity sha512-mJKxI3Vinj5kPEXR+XZXch11T18D7nHBle4+pcVmh675xlXRVTTvptYf7Qm0x9FMdjq4D6d1gJOeyxjz8YKaIg==
"@bazel/typescript@4.4.6":
version "4.4.6"
@@ -390,13 +402,6 @@
dependencies:
google-protobuf "^3.6.1"
-"@bazel/worker@4.6.1":
- version "4.6.1"
- resolved "https://registry.yarnpkg.com/@bazel/worker/-/worker-4.6.1.tgz#96925f5819344225d4fe40ffa630a3c5f4847a0b"
- integrity sha512-D6TsHxGSljmlLoz8FXL1+ISh8XnDuRkBpT6Mz0wD62eWajUZASTfX9I4HNiLNbsWY4Omc7nKXI+j4R8/BLciFg==
- dependencies:
- google-protobuf "^3.6.1"
-
"@gar/promisify@^1.0.1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.2.tgz#30aa825f11d438671d585bd44e7fd564535fc210"
@@ -520,7 +525,7 @@
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
-"@rollup/plugin-node-resolve@latest":
+"@rollup/plugin-node-resolve@13.1.3":
version "13.1.3"
resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.1.3.tgz#2ed277fb3ad98745424c1d2ba152484508a92d79"
integrity sha512-BdxNk+LtmElRo5d06MGY4zoepyrXX1tkzX2hrnPEZ53k78GuOMWLqmJDGIIOPwVRIFZrLQOo+Yr6KtCuLIA0AQ==
@@ -541,13 +546,13 @@
estree-walker "^1.0.1"
picomatch "^2.2.2"
-"@schematics/angular@13.1.4":
- version "13.1.4"
- resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-13.1.4.tgz#8b8c9ad40403c485bae9adeb51649711651189d2"
- integrity sha512-P1YsHn1LLAmdpB9X2TBuUgrvEW/KaoBbHr8ifYO8/uQEXyeiIF+So8h/dnegkYkdsr3OwQ2X/j3UF6/+HS0odg==
+"@schematics/angular@13.2.0":
+ version "13.2.0"
+ resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-13.2.0.tgz#fee1ef0810d16d7090822233e6e6e01a91a04a2c"
+ integrity sha512-DlUJ+ix9u/wz7IWc82dix5xsDGu0nztZ6Litrv+EsFDRYc95IFxTWuNwwjL2eRkI2KLIk79wmO7xhlUwrUyNlg==
dependencies:
- "@angular-devkit/core" "13.1.4"
- "@angular-devkit/schematics" "13.1.4"
+ "@angular-devkit/core" "13.2.0"
+ "@angular-devkit/schematics" "13.2.0"
jsonc-parser "3.0.0"
"@socket.io/base64-arraybuffer@~1.0.2":
@@ -560,6 +565,11 @@
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
+"@tootallnate/once@2":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
+ integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
+
"@types/component-emitter@^1.2.10":
version "1.2.11"
resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506"
@@ -580,12 +590,12 @@
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
-"@types/flatbuffers@latest":
+"@types/flatbuffers@1.10.0":
version "1.10.0"
resolved "https://registry.yarnpkg.com/@types/flatbuffers/-/flatbuffers-1.10.0.tgz#aa74e30ffdc86445f2f060e1808fc9d56b5603ba"
integrity sha512-7btbphLrKvo5yl/5CC2OCxUSMx1wV1wvGT1qDXkSt7yi00/YW7E8k6qzXqJHsp+WU0eoG7r6MTQQXI9lIvd0qA==
-"@types/jasmine@latest":
+"@types/jasmine@3.10.3":
version "3.10.3"
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.10.3.tgz#a89798b3d5a8bd23ca56e855a9aee3e5a93bdaaa"
integrity sha512-SWyMrjgdAUHNQmutvDcKablrJhkDLy4wunTme8oYLjKp41GnHGxMRXr2MQMvy/qy8H3LdzwQk9gH4hZ6T++H8g==
@@ -600,6 +610,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.8.tgz#50d680c8a8a78fe30abe6906453b21ad8ab0ad7b"
integrity sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg==
+"@types/node@17.0.21":
+ version "17.0.21"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644"
+ integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==
+
"@types/node@>=10.0.0":
version "17.0.10"
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.10.tgz#616f16e9d3a2a3d618136b1be244315d95bd7cab"
@@ -610,10 +625,10 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.18.tgz#b7d45fc950e6ffd7edc685e890d13aa7b8535dce"
integrity sha512-ryO3Q3++yZC/+b8j8BdKd/dn9JlzlHBPdm80656xwYUdmPkpTGTjkAdt6BByiNupGPE8w0FhBgvYy/fX9hRNGQ==
-"@types/node@latest":
- version "17.0.12"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.12.tgz#f7aa331b27f08244888c47b7df126184bc2339c5"
- integrity sha512-4YpbAsnJXWYK/fpTVFlMIcUIho2AYCi4wg5aNPrG1ng7fn/1/RZfCIpRCiBX+12RVa34RluilnvCqD+g3KiSiA==
+"@types/q@^0.0.32":
+ version "0.0.32"
+ resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5"
+ integrity sha1-vShOV8hPEyXacCur/IKlMoGQwMU=
"@types/resolve@1.17.1":
version "1.17.1"
@@ -622,6 +637,11 @@
dependencies:
"@types/node" "*"
+"@types/selenium-webdriver@^3.0.0":
+ version "3.0.19"
+ resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.19.tgz#28ecede76f15b13553b4e86074d4cf9a0bbe49c4"
+ integrity sha512-OFUilxQg+rWL2FMxtmIgCkUDlJB6pskkpvmew7yeXfzzsOBb5rc+y2+DjHm+r3r1ZPPcJefK3DveNSYWGiy68g==
+
"@yarnpkg/lockfile@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31"
@@ -640,6 +660,11 @@
mime-types "~2.1.24"
negotiator "0.6.2"
+adm-zip@^0.4.9:
+ version "0.4.16"
+ resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365"
+ integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==
+
agent-base@6, agent-base@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
@@ -647,6 +672,13 @@
dependencies:
debug "4"
+agent-base@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
+ integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
+ dependencies:
+ es6-promisify "^5.0.0"
+
agentkeepalive@^4.1.3:
version "4.2.0"
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.0.tgz#616ce94ccb41d1a39a45d203d8076fe98713062d"
@@ -656,6 +688,15 @@
depd "^1.1.2"
humanize-ms "^1.2.1"
+agentkeepalive@^4.2.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717"
+ integrity sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==
+ dependencies:
+ debug "^4.1.0"
+ depd "^1.1.2"
+ humanize-ms "^1.2.1"
+
aggregate-error@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
@@ -671,17 +712,7 @@
dependencies:
ajv "^8.0.0"
-ajv@8.8.2:
- version "8.8.2"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.8.2.tgz#01b4fef2007a28bf75f0b7fc009f62679de4abbb"
- integrity sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==
- dependencies:
- fast-deep-equal "^3.1.1"
- json-schema-traverse "^1.0.0"
- require-from-string "^2.0.2"
- uri-js "^4.2.2"
-
-ajv@^8.0.0:
+ajv@8.9.0, ajv@^8.0.0:
version "8.9.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.9.0.tgz#738019146638824dea25edcf299dcba1b0e7eb18"
integrity sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==
@@ -691,6 +722,16 @@
require-from-string "^2.0.2"
uri-js "^4.2.2"
+ajv@^6.12.3:
+ version "6.12.6"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
+
ansi-colors@4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
@@ -703,11 +744,21 @@
dependencies:
type-fest "^0.21.3"
+ansi-regex@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+ integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
+
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+ansi-styles@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+ integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
+
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
@@ -743,6 +794,50 @@
delegates "^1.0.0"
readable-stream "^3.6.0"
+array-union@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
+ integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=
+ dependencies:
+ array-uniq "^1.0.1"
+
+array-uniq@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
+ integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=
+
+arrify@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+ integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
+
+asn1@~0.2.3:
+ version "0.2.6"
+ resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d"
+ integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==
+ dependencies:
+ safer-buffer "~2.1.0"
+
+assert-plus@1.0.0, assert-plus@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+ integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+ integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
+
+aws-sign2@~0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
+ integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
+
+aws4@^1.8.0:
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
+ integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
+
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
@@ -758,6 +853,13 @@
resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6"
integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==
+bcrypt-pbkdf@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
+ integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
+ dependencies:
+ tweetnacl "^0.14.3"
+
binary-extensions@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
@@ -772,6 +874,13 @@
inherits "^2.0.4"
readable-stream "^3.4.0"
+blocking-proxy@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/blocking-proxy/-/blocking-proxy-1.0.1.tgz#81d6fd1fe13a4c0d6957df7f91b75e98dac40cb2"
+ integrity sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==
+ dependencies:
+ minimist "^1.2.0"
+
body-parser@^1.19.0:
version "1.19.1"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4"
@@ -814,6 +923,13 @@
node-releases "^2.0.1"
picocolors "^1.0.0"
+browserstack@^1.5.1:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/browserstack/-/browserstack-1.6.1.tgz#e051f9733ec3b507659f395c7a4765a1b1e358b3"
+ integrity sha512-GxtFjpIaKdbAyzHfFDKixKO8IBT7wR3NjbzrGc78nNs/Ciys9wU3/nBtsqsWv5nDSrdI5tz0peKuzCPuNXNUiw==
+ dependencies:
+ https-proxy-agent "^2.2.1"
+
buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
@@ -841,7 +957,7 @@
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a"
integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==
-cacache@^15.0.5, cacache@^15.2.0:
+cacache@^15.0.5, cacache@^15.2.0, cacache@^15.3.0:
version "15.3.0"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb"
integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==
@@ -865,6 +981,11 @@
tar "^6.0.2"
unique-filename "^1.1.1"
+camelcase@^5.0.0:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+ integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
caniuse-lite@^1.0.30001286:
version "1.0.30001299"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001299.tgz#d753bf6444ed401eb503cbbe17aa3e1451b5a68c"
@@ -875,6 +996,22 @@
resolved "https://registry.yarnpkg.com/canonical-path/-/canonical-path-1.0.0.tgz#fcb470c23958def85081856be7a86e904f180d1d"
integrity sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==
+caseless@~0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+ integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
+
+chalk@^1.1.1, chalk@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+ integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
+ dependencies:
+ ansi-styles "^2.2.1"
+ escape-string-regexp "^1.0.2"
+ has-ansi "^2.0.0"
+ strip-ansi "^3.0.0"
+ supports-color "^2.0.0"
+
chalk@^2.0.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
@@ -954,6 +1091,15 @@
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
+cliui@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
+ integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
+ dependencies:
+ string-width "^4.2.0"
+ strip-ansi "^6.0.0"
+ wrap-ansi "^6.2.0"
+
cliui@^7.0.2:
version "7.0.4"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
@@ -1002,6 +1148,13 @@
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
+combined-stream@^1.0.6, combined-stream@~1.0.6:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
commander@^2.20.0:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@@ -1054,6 +1207,16 @@
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1"
integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==
+core-util-is@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+ integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
+
+core-util-is@~1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
+ integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
+
cors@~2.8.5:
version "2.8.5"
resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
@@ -1067,6 +1230,13 @@
resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425"
integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=
+dashdash@^1.12.0:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
+ integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
+ dependencies:
+ assert-plus "^1.0.0"
+
date-format@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.3.tgz#f63de5dc08dc02efd8ef32bf2a6918e486f35873"
@@ -1086,6 +1256,18 @@
dependencies:
ms "2.1.2"
+debug@^3.1.0:
+ version "3.2.7"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
+ integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
+ dependencies:
+ ms "^2.1.1"
+
+decamelize@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+ integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+
deepmerge@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
@@ -1103,6 +1285,24 @@
resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
+del@^2.2.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
+ integrity sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=
+ dependencies:
+ globby "^5.0.0"
+ is-path-cwd "^1.0.0"
+ is-path-in-cwd "^1.0.0"
+ object-assign "^4.0.1"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+ rimraf "^2.2.8"
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+ integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
+
delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
@@ -1133,6 +1333,14 @@
extend "^3.0.0"
void-elements "^2.0.0"
+ecc-jsbn@~0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
+ integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
+ dependencies:
+ jsbn "~0.1.0"
+ safer-buffer "^2.1.0"
+
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -1153,7 +1361,7 @@
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
-encoding@^0.1.12:
+encoding@^0.1.12, encoding@^0.1.13:
version "0.1.13"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==
@@ -1198,6 +1406,18 @@
resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9"
integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==
+es6-promise@^4.0.3:
+ version "4.2.8"
+ resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
+ integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
+
+es6-promisify@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
+ integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
+ dependencies:
+ es6-promise "^4.0.3"
+
escalade@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
@@ -1208,7 +1428,7 @@
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
-escape-string-regexp@^1.0.5:
+escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
@@ -1223,7 +1443,12 @@
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
-extend@^3.0.0:
+exit@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
+ integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=
+
+extend@^3.0.0, extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
@@ -1237,12 +1462,22 @@
iconv-lite "^0.4.24"
tmp "^0.0.33"
+extsprintf@1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
+ integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
+
+extsprintf@^1.2.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07"
+ integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==
+
fast-deep-equal@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
-fast-json-stable-stringify@2.1.0:
+fast-json-stable-stringify@2.1.0, fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
@@ -1274,6 +1509,14 @@
statuses "~1.5.0"
unpipe "~1.0.0"
+find-up@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
+ integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+ dependencies:
+ locate-path "^5.0.0"
+ path-exists "^4.0.0"
+
flatted@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2"
@@ -1284,6 +1527,20 @@
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685"
integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==
+forever-agent@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
+ integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
+
+form-data@~2.3.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
+ integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.6"
+ mime-types "^2.1.12"
+
fs-extra@^10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1"
@@ -1340,11 +1597,18 @@
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
-get-caller-file@^2.0.5:
+get-caller-file@^2.0.1, get-caller-file@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+getpass@^0.1.1:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
+ integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
+ dependencies:
+ assert-plus "^1.0.0"
+
glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
@@ -1352,7 +1616,7 @@
dependencies:
is-glob "^4.0.1"
-glob@^7.0.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7:
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.6, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7:
version "7.2.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
@@ -1369,6 +1633,18 @@
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+globby@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
+ integrity sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=
+ dependencies:
+ array-union "^1.0.1"
+ arrify "^1.0.0"
+ glob "^7.0.3"
+ object-assign "^4.0.1"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+
google-protobuf@^3.6.1:
version "3.19.1"
resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.19.1.tgz#5af5390e8206c446d8f49febaffd4b7f4ac28f41"
@@ -1379,6 +1655,26 @@
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
+har-schema@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
+ integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
+
+har-validator@~5.1.3:
+ version "5.1.5"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
+ integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
+ dependencies:
+ ajv "^6.12.3"
+ har-schema "^2.0.0"
+
+has-ansi@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+ integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
+ dependencies:
+ ansi-regex "^2.0.0"
+
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@@ -1433,6 +1729,15 @@
agent-base "6"
debug "4"
+http-proxy-agent@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
+ integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
+ dependencies:
+ "@tootallnate/once" "2"
+ agent-base "6"
+ debug "4"
+
http-proxy@^1.18.1:
version "1.18.1"
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
@@ -1442,6 +1747,23 @@
follow-redirects "^1.0.0"
requires-port "^1.0.0"
+http-signature@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
+ integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
+ dependencies:
+ assert-plus "^1.0.0"
+ jsprim "^1.2.2"
+ sshpk "^1.7.0"
+
+https-proxy-agent@^2.2.1:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
+ integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
+ dependencies:
+ agent-base "^4.3.0"
+ debug "^3.1.0"
+
https-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
@@ -1483,6 +1805,11 @@
dependencies:
minimatch "^3.0.4"
+immediate@~3.0.5:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
+ integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=
+
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
@@ -1506,7 +1833,7 @@
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4:
+inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -1516,6 +1843,11 @@
resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5"
integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==
+ini@^1.3.4:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
+ integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
+
inquirer@8.2.0:
version "8.2.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.0.tgz#f44f008dd344bbfc4b30031f45d984e034a3ac3a"
@@ -1548,7 +1880,7 @@
dependencies:
binary-extensions "^2.0.0"
-is-core-module@^2.2.0, is-core-module@^2.8.0:
+is-core-module@^2.8.0, is-core-module@^2.8.1:
version "2.8.1"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211"
integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==
@@ -1597,6 +1929,30 @@
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+is-path-cwd@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
+ integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=
+
+is-path-in-cwd@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52"
+ integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==
+ dependencies:
+ is-path-inside "^1.0.0"
+
+is-path-inside@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
+ integrity sha1-jvW33lBDej/cprToZe96pVy0gDY=
+ dependencies:
+ path-is-inside "^1.0.1"
+
+is-typedarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+ integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
+
is-unicode-supported@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
@@ -1609,6 +1965,11 @@
dependencies:
is-docker "^2.0.0"
+isarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+ integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
+
isbinaryfile@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.8.tgz#5d34b94865bd4946633ecc78a026fc76c5b11fcf"
@@ -1619,29 +1980,58 @@
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
+isstream@~0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+ integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
+
jasmine-core@^3.6.0:
version "3.99.0"
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.99.0.tgz#99a3da0d38ba2de82614d9198b7b1bc1c32a5960"
integrity sha512-+ZDaJlEfRopINQqgE+hvzRyDIQDeKfqqTvF8RzXsvU1yE3pBDRud2+Qfh9WvGgRpuzqxyQJVI6Amy5XQ11r/3w==
-jasmine-core@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-4.0.0.tgz#8299ed38a100c47a1d154af63449a40967a7be5c"
- integrity sha512-tq24OCqHElgU9KDpb/8O21r1IfotgjIzalfW9eCmRR40LZpvwXT68iariIyayMwi0m98RDt16aljdbwK0sBMmQ==
+jasmine-core@~2.8.0:
+ version "2.8.0"
+ resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.8.0.tgz#bcc979ae1f9fd05701e45e52e65d3a5d63f1a24e"
+ integrity sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=
-jasmine@latest:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-4.0.2.tgz#6f5ff7fbf6b67f56600235fdb7d299ac52876c4b"
- integrity sha512-YsrgxJQEggxzByYe4j68eQLOiQeSrPDYGv4sHhGBp3c6HHdq+uPXeAQ73kOAQpdLZ3/0zN7x/TZTloqeE1/qIA==
+jasmine-core@~3.10.0:
+ version "3.10.1"
+ resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.10.1.tgz#7aa6fa2b834a522315c651a128d940eca553989a"
+ integrity sha512-ooZWSDVAdh79Rrj4/nnfklL3NQVra0BcuhcuWoAwwi+znLDoUeH87AFfeX8s+YeYi6xlv5nveRyaA1v7CintfA==
+
+jasmine@2.8.0:
+ version "2.8.0"
+ resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-2.8.0.tgz#6b089c0a11576b1f16df11b80146d91d4e8b8a3e"
+ integrity sha1-awicChFXax8W3xG4AUbZHU6Lij4=
+ dependencies:
+ exit "^0.1.2"
+ glob "^7.0.6"
+ jasmine-core "~2.8.0"
+
+jasmine@3.10.0:
+ version "3.10.0"
+ resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-3.10.0.tgz#acd3cd560a9d20d8fdad6bd2dd05867d188503f3"
+ integrity sha512-2Y42VsC+3CQCTzTwJezOvji4qLORmKIE0kwowWC+934Krn6ZXNQYljiwK5st9V3PVx96BSiDYXSB60VVah3IlQ==
dependencies:
glob "^7.1.6"
- jasmine-core "^4.0.0"
+ jasmine-core "~3.10.0"
+
+jasminewd2@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.2.0.tgz#e37cf0b17f199cce23bea71b2039395246b4ec4e"
+ integrity sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=
js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+jsbn@~0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
+ integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
+
jsesc@^2.5.1:
version "2.5.2"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
@@ -1652,11 +2042,26 @@
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
+json-schema-traverse@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
json-schema-traverse@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+json-schema@0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
+ integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==
+
+json-stringify-safe@~5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+ integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
+
json5@^2.1.2:
version "2.2.0"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
@@ -1683,14 +2088,34 @@
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=
-karma-chrome-launcher@latest:
+jsprim@^1.2.2:
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb"
+ integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==
+ dependencies:
+ assert-plus "1.0.0"
+ extsprintf "1.3.0"
+ json-schema "0.4.0"
+ verror "1.10.0"
+
+jszip@^3.1.3:
+ version "3.7.1"
+ resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.7.1.tgz#bd63401221c15625a1228c556ca8a68da6fda3d9"
+ integrity sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==
+ dependencies:
+ lie "~3.3.0"
+ pako "~1.0.2"
+ readable-stream "~2.3.6"
+ set-immediate-shim "~1.0.1"
+
+karma-chrome-launcher@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz#805a586799a4d05f4e54f72a204979f3f3066738"
integrity sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==
dependencies:
which "^1.2.1"
-karma-firefox-launcher@latest:
+karma-firefox-launcher@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/karma-firefox-launcher/-/karma-firefox-launcher-2.1.2.tgz#9a38cc783c579a50f3ed2a82b7386186385cfc2d"
integrity sha512-VV9xDQU1QIboTrjtGVD4NCfzIH7n01ZXqy/qpBhnOeGVOkG5JYPEm8kuSd7psHE6WouZaQ9Ool92g8LFweSNMA==
@@ -1698,29 +2123,29 @@
is-wsl "^2.2.0"
which "^2.0.1"
-karma-jasmine@latest:
+karma-jasmine@4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-4.0.1.tgz#b99e073b6d99a5196fc4bffc121b89313b0abd82"
integrity sha512-h8XDAhTiZjJKzfkoO1laMH+zfNlra+dEQHUAjpn5JV1zCPtOIVWGQjLBrqhnzQa/hrU2XrZwSyBa6XjEBzfXzw==
dependencies:
jasmine-core "^3.6.0"
-karma-requirejs@latest:
+karma-requirejs@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/karma-requirejs/-/karma-requirejs-1.1.0.tgz#fddae2cb87d7ebc16fb0222893564d7fee578798"
integrity sha1-/driy4fX68FvsCIok1ZNf+5Xh5g=
-karma-sourcemap-loader@latest:
+karma-sourcemap-loader@0.3.8:
version "0.3.8"
resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.8.tgz#d4bae72fb7a8397328a62b75013d2df937bdcf9c"
integrity sha512-zorxyAakYZuBcHRJE+vbrK2o2JXLFWK8VVjiT/6P+ltLBUGUvqTEkUiQ119MGdOrK7mrmxXHZF1/pfT6GgIZ6g==
dependencies:
graceful-fs "^4.1.2"
-karma@latest:
- version "6.3.11"
- resolved "https://registry.yarnpkg.com/karma/-/karma-6.3.11.tgz#2c2fb09f1a9f52e1a0739adeedace2a68d4c0d34"
- integrity sha512-QGUh4yXgizzDNPLB5nWTvP+wysKexngbyLVWFOyikB661hpa2RZLf5anZQzqliWtAQuYVep0ot0D1U7UQKpsxQ==
+karma@6.3.12:
+ version "6.3.12"
+ resolved "https://registry.yarnpkg.com/karma/-/karma-6.3.12.tgz#fe6347f027385fc16da1a9bb87d766e2d25981c6"
+ integrity sha512-qwIG+oB2YmHx4hjvYSRMNzL3YWAJ9baHaLAxiP7biFNkfpwYTUTtPck0joFpucalNLzMr+7z/FX1uY/kl8DV9A==
dependencies:
body-parser "^1.19.0"
braces "^3.0.2"
@@ -1746,6 +2171,20 @@
ua-parser-js "^0.7.30"
yargs "^16.1.1"
+lie@~3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
+ integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==
+ dependencies:
+ immediate "~3.0.5"
+
+locate-path@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
+ integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+ dependencies:
+ p-locate "^4.1.0"
+
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
@@ -1782,6 +2221,11 @@
dependencies:
yallist "^4.0.0"
+lru-cache@^7.4.0:
+ version "7.4.1"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.4.1.tgz#afe07e885ef0cd5bf99f62f4fa7545d48746d779"
+ integrity sha512-NCD7/WRlFmADccuHjsRUYqdluYBr//n/O0fesCb/n52FoGcgKh8o4Dpm7YIbZwVcDs8rPBQbCZLmWWsp6m+xGQ==
+
magic-string@0.25.7, magic-string@^0.25.0:
version "0.25.7"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
@@ -1797,7 +2241,29 @@
pify "^4.0.1"
semver "^5.6.0"
-make-fetch-happen@^9.0.1, make-fetch-happen@^9.1.0:
+make-fetch-happen@^10.0.1:
+ version "10.0.4"
+ resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-10.0.4.tgz#309823c7a2b4c947465274220e169112c977b94f"
+ integrity sha512-CiReW6usy3UXby5N46XjWfLPFPq1glugCszh18I0NYJCwr129ZAx9j3Dlv+cRsK0q3VjlVysEzhdtdw2+NhdYA==
+ dependencies:
+ agentkeepalive "^4.2.1"
+ cacache "^15.3.0"
+ http-cache-semantics "^4.1.0"
+ http-proxy-agent "^5.0.0"
+ https-proxy-agent "^5.0.0"
+ is-lambda "^1.0.1"
+ lru-cache "^7.4.0"
+ minipass "^3.1.6"
+ minipass-collect "^1.0.2"
+ minipass-fetch "^2.0.1"
+ minipass-flush "^1.0.5"
+ minipass-pipeline "^1.2.4"
+ negotiator "^0.6.3"
+ promise-retry "^2.0.1"
+ socks-proxy-agent "^6.1.1"
+ ssri "^8.0.1"
+
+make-fetch-happen@^9.1.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968"
integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==
@@ -1829,7 +2295,7 @@
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c"
integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==
-mime-types@~2.1.24:
+mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24:
version "2.1.34"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24"
integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==
@@ -1853,7 +2319,7 @@
dependencies:
brace-expansion "^1.1.7"
-minimist@^1.2.5:
+minimist@^1.2.0, minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
@@ -1865,7 +2331,7 @@
dependencies:
minipass "^3.0.0"
-minipass-fetch@^1.3.0, minipass-fetch@^1.3.2:
+minipass-fetch@^1.3.2, minipass-fetch@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.4.1.tgz#d75e0091daac1b0ffd7e9d41629faff7d0c1f1b6"
integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==
@@ -1876,6 +2342,17 @@
optionalDependencies:
encoding "^0.1.12"
+minipass-fetch@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-2.0.2.tgz#5ea5fb9a2e24ccd3cfb489563540bb4024fc6c31"
+ integrity sha512-M63u5yWX0yxY1C3DcLVY1xWai0pNM3qa1xCMXFgdejY5F/NTmyzNVHGcBxKerX51lssqxwWWTjpg/ZPuD39gOQ==
+ dependencies:
+ minipass "^3.1.6"
+ minipass-sized "^1.0.3"
+ minizlib "^2.1.2"
+ optionalDependencies:
+ encoding "^0.1.13"
+
minipass-flush@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373"
@@ -1905,14 +2382,14 @@
dependencies:
minipass "^3.0.0"
-minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3:
+minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3, minipass@^3.1.6:
version "3.1.6"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee"
integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==
dependencies:
yallist "^4.0.0"
-minizlib@^2.0.0, minizlib@^2.1.1:
+minizlib@^2.0.0, minizlib@^2.1.1, minizlib@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
@@ -1935,7 +2412,7 @@
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-ms@^2.0.0:
+ms@^2.0.0, ms@^2.1.1:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
@@ -1950,6 +2427,11 @@
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
+negotiator@^0.6.3:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
+ integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
+
node-gyp@^8.2.0:
version "8.4.1"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937"
@@ -2002,7 +2484,7 @@
resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2"
integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==
-npm-package-arg@8.1.5, npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-package-arg@^8.1.2:
+npm-package-arg@8.1.5, npm-package-arg@^8.0.1, npm-package-arg@^8.1.2, npm-package-arg@^8.1.5:
version "8.1.5"
resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-8.1.5.tgz#3369b2d5fe8fdc674baa7f1786514ddc15466e44"
integrity sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==
@@ -2031,17 +2513,17 @@
npm-package-arg "^8.1.2"
semver "^7.3.4"
-npm-registry-fetch@^11.0.0:
- version "11.0.0"
- resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz#68c1bb810c46542760d62a6a965f85a702d43a76"
- integrity sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA==
+npm-registry-fetch@^12.0.0:
+ version "12.0.2"
+ resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-12.0.2.tgz#ae583bb3c902a60dae43675b5e33b5b1f6159f1e"
+ integrity sha512-Df5QT3RaJnXYuOwtXBXS9BWs+tHH2olvkCLh6jcR/b/u3DvPMlp3J0TvvYwplPKxHMOwfg287PYih9QqaVFoKA==
dependencies:
- make-fetch-happen "^9.0.1"
- minipass "^3.1.3"
- minipass-fetch "^1.3.0"
+ make-fetch-happen "^10.0.1"
+ minipass "^3.1.6"
+ minipass-fetch "^1.4.1"
minipass-json-stream "^1.0.1"
- minizlib "^2.0.0"
- npm-package-arg "^8.0.0"
+ minizlib "^2.1.2"
+ npm-package-arg "^8.1.5"
npmlog@^6.0.0:
version "6.0.0"
@@ -2053,7 +2535,12 @@
gauge "^4.0.0"
set-blocking "^2.0.0"
-object-assign@^4:
+oauth-sign@~0.9.0:
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
+ integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
+
+object-assign@^4, object-assign@^4.0.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@@ -2103,11 +2590,25 @@
strip-ansi "^6.0.0"
wcwidth "^1.0.1"
-os-tmpdir@~1.0.2:
+os-tmpdir@~1.0.1, os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
+p-limit@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
+ integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+ dependencies:
+ p-try "^2.0.0"
+
+p-locate@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
+ integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+ dependencies:
+ p-limit "^2.2.0"
+
p-map@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
@@ -2115,10 +2616,15 @@
dependencies:
aggregate-error "^3.0.0"
-pacote@12.0.2:
- version "12.0.2"
- resolved "https://registry.yarnpkg.com/pacote/-/pacote-12.0.2.tgz#14ae30a81fe62ec4fc18c071150e6763e932527c"
- integrity sha512-Ar3mhjcxhMzk+OVZ8pbnXdb0l8+pimvlsqBGRNkble2NVgyqOGE3yrCGi/lAYq7E7NRDMz89R1Wx5HIMCGgeYg==
+p-try@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+pacote@12.0.3:
+ version "12.0.3"
+ resolved "https://registry.yarnpkg.com/pacote/-/pacote-12.0.3.tgz#b6f25868deb810e7e0ddf001be88da2bcaca57c7"
+ integrity sha512-CdYEl03JDrRO3x18uHjBYA9TyoW8gy+ThVcypcDkxPtKlw76e4ejhYB6i9lJ+/cebbjpqPW/CijjqxwDTts8Ow==
dependencies:
"@npmcli/git" "^2.1.0"
"@npmcli/installed-package-contents" "^1.0.6"
@@ -2133,28 +2639,48 @@
npm-package-arg "^8.0.1"
npm-packlist "^3.0.0"
npm-pick-manifest "^6.0.0"
- npm-registry-fetch "^11.0.0"
+ npm-registry-fetch "^12.0.0"
promise-retry "^2.0.1"
read-package-json-fast "^2.0.1"
rimraf "^3.0.2"
ssri "^8.0.1"
tar "^6.1.0"
+pako@~1.0.2:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
+ integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
+
parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
-path-parse@^1.0.6, path-parse@^1.0.7:
+path-is-inside@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+ integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
+
+path-parse@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+performance-now@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
+ integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
+
picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
@@ -2165,11 +2691,33 @@
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+pify@^2.0.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+ integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
+
pify@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
+pinkie-promise@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+ integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
+ dependencies:
+ pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+ integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
+
+process-nextick-args@~2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
+ integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
+
promise-inflight@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
@@ -2202,11 +2750,47 @@
"@types/node" "^10.1.0"
long "^4.0.0"
-punycode@^2.1.0:
+protractor@7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/protractor/-/protractor-7.0.0.tgz#c3e263608bd72e2c2dc802b11a772711a4792d03"
+ integrity sha512-UqkFjivi4GcvUQYzqGYNe0mLzfn5jiLmO8w9nMhQoJRLhy2grJonpga2IWhI6yJO30LibWXJJtA4MOIZD2GgZw==
+ dependencies:
+ "@types/q" "^0.0.32"
+ "@types/selenium-webdriver" "^3.0.0"
+ blocking-proxy "^1.0.0"
+ browserstack "^1.5.1"
+ chalk "^1.1.3"
+ glob "^7.0.3"
+ jasmine "2.8.0"
+ jasminewd2 "^2.1.0"
+ q "1.4.1"
+ saucelabs "^1.5.0"
+ selenium-webdriver "3.6.0"
+ source-map-support "~0.4.0"
+ webdriver-js-extender "2.1.0"
+ webdriver-manager "^12.1.7"
+ yargs "^15.3.1"
+
+psl@^1.1.28:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
+ integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
+
+punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
+q@1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e"
+ integrity sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=
+
+q@^1.4.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
+ integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
+
qjobs@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071"
@@ -2217,6 +2801,11 @@
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee"
integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==
+qs@~6.5.2:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"
+ integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
+
range-parser@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
@@ -2249,6 +2838,19 @@
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
+readable-stream@~2.3.6:
+ version "2.3.7"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
+ integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~2.0.0"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.1.1"
+ util-deprecate "~1.0.1"
+
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
@@ -2261,6 +2863,32 @@
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==
+request@^2.87.0:
+ version "2.88.2"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
+ integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
+ dependencies:
+ aws-sign2 "~0.7.0"
+ aws4 "^1.8.0"
+ caseless "~0.12.0"
+ combined-stream "~1.0.6"
+ extend "~3.0.2"
+ forever-agent "~0.6.1"
+ form-data "~2.3.2"
+ har-validator "~5.1.3"
+ http-signature "~1.2.0"
+ is-typedarray "~1.0.0"
+ isstream "~0.1.2"
+ json-stringify-safe "~5.0.1"
+ mime-types "~2.1.19"
+ oauth-sign "~0.9.0"
+ performance-now "^2.1.0"
+ qs "~6.5.2"
+ safe-buffer "^5.1.2"
+ tough-cookie "~2.5.0"
+ tunnel-agent "^0.6.0"
+ uuid "^3.3.2"
+
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
@@ -2271,7 +2899,12 @@
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
-requirejs@latest:
+require-main-filename@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
+ integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
+
+requirejs@2.3.6:
version "2.3.6"
resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.6.tgz#e5093d9601c2829251258c0b9445d4d19fa9e7c9"
integrity sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==
@@ -2281,13 +2914,14 @@
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
-resolve@1.20.0:
- version "1.20.0"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
- integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
+resolve@1.22.0:
+ version "1.22.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198"
+ integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==
dependencies:
- is-core-module "^2.2.0"
- path-parse "^1.0.6"
+ is-core-module "^2.8.1"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
resolve@^1.19.0:
version "1.21.0"
@@ -2316,6 +2950,13 @@
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
+rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
+ integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
+ dependencies:
+ glob "^7.1.3"
+
rimraf@^3.0.0, rimraf@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
@@ -2323,10 +2964,10 @@
dependencies:
glob "^7.1.3"
-rollup@latest:
- version "2.64.0"
- resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.64.0.tgz#f0f59774e21fbb56de438a37d06a2189632b207a"
- integrity sha512-+c+lbw1lexBKSMb1yxGDVfJ+vchJH3qLbmavR+awDinTDA2C5Ug9u7lkOzj62SCu0PKUExsW36tpgW7Fmpn3yQ==
+rollup@2.66.1:
+ version "2.66.1"
+ resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.66.1.tgz#366b0404de353c4331d538c3ad2963934fcb4937"
+ integrity sha512-crSgLhSkLMnKr4s9iZ/1qJCplgAgrRY+igWv8KhG/AjKOJ0YX/WpmANyn8oxrw+zenF3BXWDLa7Xl/QZISH+7w==
optionalDependencies:
fsevents "~2.3.2"
@@ -2349,21 +2990,43 @@
dependencies:
tslib "^2.1.0"
-safe-buffer@~5.1.1:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
- integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-
-safe-buffer@~5.2.0:
+safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
-"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0":
+safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+ integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
+"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+saucelabs@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/saucelabs/-/saucelabs-1.5.0.tgz#9405a73c360d449b232839919a86c396d379fd9d"
+ integrity sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==
+ dependencies:
+ https-proxy-agent "^2.2.1"
+
+sax@>=0.6.0:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+ integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
+
+selenium-webdriver@3.6.0, selenium-webdriver@^3.0.1:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz#2ba87a1662c020b8988c981ae62cb2a01298eafc"
+ integrity sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==
+ dependencies:
+ jszip "^3.1.3"
+ rimraf "^2.5.4"
+ tmp "0.0.30"
+ xml2js "^0.4.17"
+
semver@5.6.0:
version "5.6.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
@@ -2376,7 +3039,7 @@
dependencies:
lru-cache "^6.0.0"
-semver@^5.6.0:
+semver@^5.3.0, semver@^5.6.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
@@ -2391,6 +3054,11 @@
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
+set-immediate-shim@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
+ integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=
+
setprototypeof@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
@@ -2437,7 +3105,7 @@
socket.io-adapter "~2.3.3"
socket.io-parser "~4.0.4"
-socks-proxy-agent@^6.0.0:
+socks-proxy-agent@^6.0.0, socks-proxy-agent@^6.1.1:
version "6.1.1"
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87"
integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==
@@ -2461,6 +3129,13 @@
buffer-from "^1.0.0"
source-map "^0.6.0"
+source-map-support@~0.4.0:
+ version "0.4.18"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
+ integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==
+ dependencies:
+ source-map "^0.5.6"
+
source-map-support@~0.5.20:
version "0.5.21"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
@@ -2474,7 +3149,7 @@
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
-source-map@^0.5.0:
+source-map@^0.5.0, source-map@^0.5.6:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@@ -2489,6 +3164,21 @@
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
+sshpk@^1.7.0:
+ version "1.17.0"
+ resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5"
+ integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==
+ dependencies:
+ asn1 "~0.2.3"
+ assert-plus "^1.0.0"
+ bcrypt-pbkdf "^1.0.0"
+ dashdash "^1.12.0"
+ ecc-jsbn "~0.1.1"
+ getpass "^0.1.1"
+ jsbn "~0.1.0"
+ safer-buffer "^2.0.2"
+ tweetnacl "~0.14.0"
+
ssri@^8.0.0, ssri@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af"
@@ -2526,6 +3216,20 @@
dependencies:
safe-buffer "~5.2.0"
+string_decoder@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+ integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
+ dependencies:
+ safe-buffer "~5.1.0"
+
+strip-ansi@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+ integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
+ dependencies:
+ ansi-regex "^2.0.0"
+
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
@@ -2533,6 +3237,11 @@
dependencies:
ansi-regex "^5.0.1"
+supports-color@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+ integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
+
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@@ -2569,7 +3278,7 @@
mkdirp "^1.0.3"
yallist "^4.0.0"
-terser@latest:
+terser@5.10.0:
version "5.10.0"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc"
integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==
@@ -2583,6 +3292,13 @@
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
+tmp@0.0.30:
+ version "0.0.30"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed"
+ integrity sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=
+ dependencies:
+ os-tmpdir "~1.0.1"
+
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@@ -2614,6 +3330,14 @@
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
+tough-cookie@~2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
+ integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
+ dependencies:
+ psl "^1.1.28"
+ punycode "^2.1.1"
+
tslib@^1.8.1:
version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
@@ -2635,6 +3359,18 @@
dependencies:
tslib "^1.8.1"
+tunnel-agent@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+ integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
+ dependencies:
+ safe-buffer "^5.0.1"
+
+tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+ version "0.14.5"
+ resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
+ integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
+
type-fest@^0.21.3:
version "0.21.3"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
@@ -2648,10 +3384,10 @@
media-typer "0.3.0"
mime-types "~2.1.24"
-typescript@latest:
- version "4.5.4"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.4.tgz#a17d3a0263bf5c8723b9c52f43c5084edf13c2e8"
- integrity sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==
+typescript@4.5.5:
+ version "4.5.5"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3"
+ integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==
ua-parser-js@^0.7.30:
version "0.7.31"
@@ -2689,7 +3425,7 @@
dependencies:
punycode "^2.1.0"
-util-deprecate@^1.0.1:
+util-deprecate@^1.0.1, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
@@ -2704,6 +3440,11 @@
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
+uuid@^3.3.2:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
+ integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
+
validate-npm-package-name@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e"
@@ -2716,6 +3457,15 @@
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
+verror@1.10.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
+ integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
+ dependencies:
+ assert-plus "^1.0.0"
+ core-util-is "1.0.2"
+ extsprintf "^1.2.0"
+
void-elements@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
@@ -2728,6 +3478,36 @@
dependencies:
defaults "^1.0.3"
+webdriver-js-extender@2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz#57d7a93c00db4cc8d556e4d3db4b5db0a80c3bb7"
+ integrity sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==
+ dependencies:
+ "@types/selenium-webdriver" "^3.0.0"
+ selenium-webdriver "^3.0.1"
+
+webdriver-manager@^12.1.7:
+ version "12.1.8"
+ resolved "https://registry.yarnpkg.com/webdriver-manager/-/webdriver-manager-12.1.8.tgz#5e70e73eaaf53a0767d5745270addafbc5905fd4"
+ integrity sha512-qJR36SXG2VwKugPcdwhaqcLQOD7r8P2Xiv9sfNbfZrKBnX243iAkOueX1yAmeNgIKhJ3YAT/F2gq6IiEZzahsg==
+ dependencies:
+ adm-zip "^0.4.9"
+ chalk "^1.1.1"
+ del "^2.2.0"
+ glob "^7.0.3"
+ ini "^1.3.4"
+ minimist "^1.2.0"
+ q "^1.4.1"
+ request "^2.87.0"
+ rimraf "^2.5.2"
+ semver "^5.3.0"
+ xml2js "^0.4.17"
+
+which-module@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
+ integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
+
which@^1.2.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
@@ -2749,6 +3529,15 @@
dependencies:
string-width "^1.0.2 || 2 || 3 || 4"
+wrap-ansi@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
+ integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
@@ -2768,6 +3557,24 @@
resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba"
integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==
+xml2js@^0.4.17:
+ version "0.4.23"
+ resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66"
+ integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==
+ dependencies:
+ sax ">=0.6.0"
+ xmlbuilder "~11.0.0"
+
+xmlbuilder@~11.0.0:
+ version "11.0.1"
+ resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
+ integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
+
+y18n@^4.0.0:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
+ integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
+
y18n@^5.0.5:
version "5.0.8"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
@@ -2778,6 +3585,14 @@
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+yargs-parser@^18.1.2:
+ version "18.1.3"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
+ integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
+ dependencies:
+ camelcase "^5.0.0"
+ decamelize "^1.2.0"
+
yargs-parser@^20.2.2:
version "20.2.9"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
@@ -2788,6 +3603,23 @@
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.0.tgz#a485d3966be4317426dd56bdb6a30131b281dc55"
integrity sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==
+yargs@^15.3.1:
+ version "15.4.1"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
+ integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
+ dependencies:
+ cliui "^6.0.0"
+ decamelize "^1.2.0"
+ find-up "^4.1.0"
+ get-caller-file "^2.0.1"
+ require-directory "^2.1.1"
+ require-main-filename "^2.0.0"
+ set-blocking "^2.0.0"
+ string-width "^4.2.0"
+ which-module "^2.0.0"
+ y18n "^4.0.0"
+ yargs-parser "^18.1.2"
+
yargs@^16.1.1:
version "16.2.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"