Scouting: Track mobility

Signed-off-by: Filip Kujawa <filip.j.kujawa@gmail.com>
Change-Id: Ie8f9521116887eef574ebd13e20ca837f009825e
diff --git a/scouting/db/db.go b/scouting/db/db.go
index 34f2dac..031f54c 100644
--- a/scouting/db/db.go
+++ b/scouting/db/db.go
@@ -39,6 +39,7 @@
 	LowCones, MiddleCones, HighCones, ConesDropped                 int32
 	SuperchargedPieces                                             int32
 	AvgCycle                                                       int64
+	Mobility                                                       bool
 	DockedAuto, EngagedAuto, BalanceAttemptAuto                    bool
 	Docked, Engaged, BalanceAttempt                                bool
 
diff --git a/scouting/db/db_test.go b/scouting/db/db_test.go
index 9c48cba..3c345b0 100644
--- a/scouting/db/db_test.go
+++ b/scouting/db/db_test.go
@@ -151,7 +151,7 @@
 			ConesDroppedAuto: 0, LowCubes: 1, MiddleCubes: 2,
 			HighCubes: 1, CubesDropped: 0, LowCones: 0,
 			MiddleCones: 2, HighCones: 1, ConesDropped: 1, SuperchargedPieces: 0,
-			AvgCycle: 0, DockedAuto: true, EngagedAuto: false,
+			AvgCycle: 0, Mobility: true, DockedAuto: true, EngagedAuto: false,
 			BalanceAttemptAuto: false, Docked: false, Engaged: false,
 			BalanceAttempt: false, CollectedBy: "emma",
 		},
@@ -163,7 +163,7 @@
 			ConesDroppedAuto: 1, LowCubes: 1, MiddleCubes: 0,
 			HighCubes: 0, CubesDropped: 1, LowCones: 0,
 			MiddleCones: 0, HighCones: 1, ConesDropped: 0, SuperchargedPieces: 1,
-			AvgCycle: 0, DockedAuto: false, EngagedAuto: false,
+			AvgCycle: 0, Mobility: false, DockedAuto: false, EngagedAuto: false,
 			BalanceAttemptAuto: true, Docked: true, Engaged: true,
 			BalanceAttempt: false, CollectedBy: "tyler",
 		},
@@ -175,7 +175,7 @@
 			ConesDroppedAuto: 1, LowCubes: 0, MiddleCubes: 0,
 			HighCubes: 2, CubesDropped: 1, LowCones: 1,
 			MiddleCones: 1, HighCones: 0, ConesDropped: 1, SuperchargedPieces: 0,
-			AvgCycle: 0, DockedAuto: false, EngagedAuto: false,
+			AvgCycle: 0, Mobility: true, DockedAuto: false, EngagedAuto: false,
 			BalanceAttemptAuto: false, Docked: false, Engaged: false,
 			BalanceAttempt: true, CollectedBy: "isaac",
 		},
@@ -187,7 +187,7 @@
 			ConesDroppedAuto: 0, LowCubes: 0, MiddleCubes: 1,
 			HighCubes: 2, CubesDropped: 1, LowCones: 0,
 			MiddleCones: 1, HighCones: 0, ConesDropped: 0, SuperchargedPieces: 0,
-			AvgCycle: 0, DockedAuto: true, EngagedAuto: true,
+			AvgCycle: 0, Mobility: false, DockedAuto: true, EngagedAuto: true,
 			BalanceAttemptAuto: true, Docked: false, Engaged: false,
 			BalanceAttempt: true, CollectedBy: "will",
 		},
@@ -199,7 +199,7 @@
 			ConesDroppedAuto: 1, LowCubes: 1, MiddleCubes: 0,
 			HighCubes: 0, CubesDropped: 2, LowCones: 1,
 			MiddleCones: 1, HighCones: 0, ConesDropped: 1, SuperchargedPieces: 0,
-			AvgCycle: 0, DockedAuto: true, EngagedAuto: false,
+			AvgCycle: 0, Mobility: true, DockedAuto: true, EngagedAuto: false,
 			BalanceAttemptAuto: false, Docked: true, Engaged: false,
 			BalanceAttempt: false, CollectedBy: "unkown",
 		},
@@ -249,7 +249,7 @@
 			ConesDroppedAuto: 0, LowCubes: 1, MiddleCubes: 2,
 			HighCubes: 1, CubesDropped: 0, LowCones: 0,
 			MiddleCones: 2, HighCones: 1, ConesDropped: 1, SuperchargedPieces: 0,
-			AvgCycle: 0, DockedAuto: true, EngagedAuto: false,
+			AvgCycle: 0, Mobility: true, DockedAuto: true, EngagedAuto: false,
 			BalanceAttemptAuto: false, Docked: false, Engaged: false,
 			BalanceAttempt: false, CollectedBy: "emma",
 		},
@@ -261,7 +261,7 @@
 			ConesDroppedAuto: 1, LowCubes: 1, MiddleCubes: 0,
 			HighCubes: 0, CubesDropped: 1, LowCones: 0,
 			MiddleCones: 0, HighCones: 1, ConesDropped: 0, SuperchargedPieces: 1,
-			AvgCycle: 0, DockedAuto: true, EngagedAuto: true,
+			AvgCycle: 0, Mobility: false, DockedAuto: true, EngagedAuto: true,
 			BalanceAttemptAuto: true, Docked: false, Engaged: false,
 			BalanceAttempt: false, CollectedBy: "tyler",
 		},
@@ -273,7 +273,7 @@
 			ConesDroppedAuto: 0, LowCubes: 1, MiddleCubes: 2,
 			HighCubes: 1, CubesDropped: 0, LowCones: 0,
 			MiddleCones: 2, HighCones: 1, ConesDropped: 1, SuperchargedPieces: 0,
-			AvgCycle: 0, DockedAuto: true, EngagedAuto: false,
+			AvgCycle: 0, Mobility: true, DockedAuto: true, EngagedAuto: false,
 			BalanceAttemptAuto: false, Docked: true, Engaged: false,
 			BalanceAttempt: true, CollectedBy: "emma",
 		},
@@ -330,7 +330,7 @@
 			ConesDroppedAuto: 1, LowCubes: 0, MiddleCubes: 1,
 			HighCubes: 2, CubesDropped: 1, LowCones: 1,
 			MiddleCones: 0, HighCones: 1, ConesDropped: 2, SuperchargedPieces: 0,
-			AvgCycle: 58, DockedAuto: false, EngagedAuto: false,
+			AvgCycle: 58, Mobility: true, DockedAuto: false, EngagedAuto: false,
 			BalanceAttemptAuto: true, Docked: true, Engaged: true,
 			BalanceAttempt: false, CollectedBy: "unknown",
 		},
@@ -342,7 +342,7 @@
 			ConesDroppedAuto: 0, LowCubes: 2, MiddleCubes: 0,
 			HighCubes: 1, CubesDropped: 0, LowCones: 0,
 			MiddleCones: 2, HighCones: 1, ConesDropped: 0, SuperchargedPieces: 1,
-			AvgCycle: 34, DockedAuto: true, EngagedAuto: true,
+			AvgCycle: 34, Mobility: true, DockedAuto: true, EngagedAuto: true,
 			BalanceAttemptAuto: false, Docked: true, Engaged: false,
 			BalanceAttempt: false, CollectedBy: "simon",
 		},
@@ -354,7 +354,7 @@
 			ConesDroppedAuto: 1, LowCubes: 0, MiddleCubes: 2,
 			HighCubes: 0, CubesDropped: 0, LowCones: 2,
 			MiddleCones: 0, HighCones: 1, ConesDropped: 1, SuperchargedPieces: 0,
-			AvgCycle: 50, DockedAuto: false, EngagedAuto: false,
+			AvgCycle: 50, Mobility: true, DockedAuto: false, EngagedAuto: false,
 			BalanceAttemptAuto: true, Docked: false, Engaged: false,
 			BalanceAttempt: false, CollectedBy: "eliza",
 		},
@@ -366,7 +366,7 @@
 			ConesDroppedAuto: 1, LowCubes: 0, MiddleCubes: 1,
 			HighCubes: 2, CubesDropped: 1, LowCones: 0,
 			MiddleCones: 2, HighCones: 1, ConesDropped: 1, SuperchargedPieces: 0,
-			AvgCycle: 49, DockedAuto: true, EngagedAuto: false,
+			AvgCycle: 49, Mobility: false, DockedAuto: true, EngagedAuto: false,
 			Docked: false, Engaged: false, CollectedBy: "isaac",
 		},
 		Stats2023{
@@ -377,7 +377,7 @@
 			ConesDroppedAuto: 1, LowCubes: 1, MiddleCubes: 2,
 			HighCubes: 0, CubesDropped: 0, LowCones: 1,
 			MiddleCones: 1, HighCones: 1, ConesDropped: 0, SuperchargedPieces: 0,
-			AvgCycle: 70, DockedAuto: true, EngagedAuto: true,
+			AvgCycle: 70, Mobility: false, DockedAuto: true, EngagedAuto: true,
 			BalanceAttemptAuto: false, Docked: false, Engaged: false,
 			BalanceAttempt: true, CollectedBy: "sam",
 		},
@@ -392,7 +392,7 @@
 			ConesDroppedAuto: 1, LowCubes: 0, MiddleCubes: 2,
 			HighCubes: 0, CubesDropped: 0, LowCones: 2,
 			MiddleCones: 0, HighCones: 1, ConesDropped: 1, SuperchargedPieces: 0,
-			AvgCycle: 50, DockedAuto: false, EngagedAuto: false,
+			AvgCycle: 50, Mobility: true, DockedAuto: false, EngagedAuto: false,
 			BalanceAttemptAuto: true, Docked: false, Engaged: false,
 			BalanceAttempt: false, CollectedBy: "eliza",
 		},
@@ -404,7 +404,7 @@
 			ConesDroppedAuto: 1, LowCubes: 1, MiddleCubes: 2,
 			HighCubes: 0, CubesDropped: 0, LowCones: 1,
 			MiddleCones: 1, HighCones: 1, ConesDropped: 0, SuperchargedPieces: 0,
-			AvgCycle: 70, DockedAuto: true, EngagedAuto: true,
+			AvgCycle: 70, Mobility: false, DockedAuto: true, EngagedAuto: true,
 			BalanceAttemptAuto: false, Docked: false, Engaged: false,
 			BalanceAttempt: true, CollectedBy: "sam",
 		},
@@ -684,7 +684,7 @@
 			ConesDroppedAuto: 1, LowCubes: 1, MiddleCubes: 2,
 			HighCubes: 1, CubesDropped: 0, LowCones: 2,
 			MiddleCones: 0, HighCones: 2, ConesDropped: 1, SuperchargedPieces: 0,
-			AvgCycle: 51, DockedAuto: true, EngagedAuto: true,
+			AvgCycle: 51, Mobility: true, DockedAuto: true, EngagedAuto: true,
 			BalanceAttemptAuto: false, Docked: false, Engaged: false,
 			BalanceAttempt: true, CollectedBy: "isaac",
 		},
@@ -696,7 +696,7 @@
 			ConesDroppedAuto: 0, LowCubes: 2, MiddleCubes: 2,
 			HighCubes: 1, CubesDropped: 0, LowCones: 1,
 			MiddleCones: 0, HighCones: 2, ConesDropped: 1, SuperchargedPieces: 1,
-			AvgCycle: 39, DockedAuto: false, EngagedAuto: false,
+			AvgCycle: 39, Mobility: false, DockedAuto: false, EngagedAuto: false,
 			BalanceAttemptAuto: true, Docked: false, Engaged: false,
 			BalanceAttempt: false, CollectedBy: "jack",
 		},
@@ -708,7 +708,7 @@
 			ConesDroppedAuto: 1, LowCubes: 2, MiddleCubes: 2,
 			HighCubes: 0, CubesDropped: 0, LowCones: 1,
 			MiddleCones: 2, HighCones: 1, ConesDropped: 1, SuperchargedPieces: 0,
-			AvgCycle: 45, DockedAuto: true, EngagedAuto: false,
+			AvgCycle: 45, Mobility: false, DockedAuto: true, EngagedAuto: false,
 			BalanceAttemptAuto: true, Docked: false, Engaged: false,
 			BalanceAttempt: true, CollectedBy: "martin",
 		},
@@ -720,7 +720,7 @@
 			ConesDroppedAuto: 1, LowCubes: 2, MiddleCubes: 2,
 			HighCubes: 0, CubesDropped: 0, LowCones: 2,
 			MiddleCones: 2, HighCones: 1, ConesDropped: 1, SuperchargedPieces: 0,
-			AvgCycle: 34, DockedAuto: true, EngagedAuto: false,
+			AvgCycle: 34, Mobility: true, DockedAuto: true, EngagedAuto: false,
 			BalanceAttemptAuto: false, Docked: true, Engaged: false,
 			BalanceAttempt: false, CollectedBy: "unknown",
 		},
diff --git a/scouting/webserver/requests/messages/request_2023_data_scouting_response.fbs b/scouting/webserver/requests/messages/request_2023_data_scouting_response.fbs
index 341b012..e532ffe 100644
--- a/scouting/webserver/requests/messages/request_2023_data_scouting_response.fbs
+++ b/scouting/webserver/requests/messages/request_2023_data_scouting_response.fbs
@@ -27,6 +27,8 @@
   supercharged_pieces:int (id:29);
   // Time in nanoseconds.
   avg_cycle: int64 (id:19);
+  // Did the robot leave its community during auto.
+  mobility: bool (id:30);
   docked_auto: bool (id:20);
   engaged_auto: bool (id:23);
   balance_attempt_auto: bool (id:27);
@@ -41,4 +43,4 @@
     stats_list:[Stats2023] (id:0);
 }
 
-root_type Request2023DataScoutingResponse;
\ No newline at end of file
+root_type Request2023DataScoutingResponse;
diff --git a/scouting/webserver/requests/messages/submit_actions.fbs b/scouting/webserver/requests/messages/submit_actions.fbs
index d269788..a0f7913 100644
--- a/scouting/webserver/requests/messages/submit_actions.fbs
+++ b/scouting/webserver/requests/messages/submit_actions.fbs
@@ -16,6 +16,10 @@
     kSupercharged,
 }
 
+table MobilityAction {
+    mobility:bool (id:0);
+}
+
 table AutoBalanceAction {
     docked:bool (id:0);
     engaged:bool (id:1);
@@ -44,6 +48,7 @@
 }
 
 union ActionType {
+    MobilityAction,
     AutoBalanceAction,
     StartMatchAction,
     PickupObjectAction,
diff --git a/scouting/webserver/requests/requests.go b/scouting/webserver/requests/requests.go
index a6ee44c..25bb6b7 100644
--- a/scouting/webserver/requests/requests.go
+++ b/scouting/webserver/requests/requests.go
@@ -397,6 +397,13 @@
 			var startMatchAction submit_actions.StartMatchAction
 			startMatchAction.Init(actionTable.Bytes, actionTable.Pos)
 			stat.StartingQuadrant = startMatchAction.Position()
+		} else if action_type == submit_actions.ActionTypeMobilityAction {
+			var mobilityAction submit_actions.MobilityAction
+			mobilityAction.Init(actionTable.Bytes, actionTable.Pos)
+			if mobilityAction.Mobility() {
+				stat.Mobility = true
+			}
+
 		} else if action_type == submit_actions.ActionTypeAutoBalanceAction {
 			var autoBalanceAction submit_actions.AutoBalanceAction
 			autoBalanceAction.Init(actionTable.Bytes, actionTable.Pos)
@@ -545,6 +552,7 @@
 			ConesDropped:       stat.ConesDropped,
 			SuperchargedPieces: stat.SuperchargedPieces,
 			AvgCycle:           stat.AvgCycle,
+			Mobility:           stat.Mobility,
 			DockedAuto:         stat.DockedAuto,
 			EngagedAuto:        stat.EngagedAuto,
 			BalanceAttemptAuto: stat.BalanceAttemptAuto,
diff --git a/scouting/webserver/requests/requests_test.go b/scouting/webserver/requests/requests_test.go
index b6f09fc..c2bc750 100644
--- a/scouting/webserver/requests/requests_test.go
+++ b/scouting/webserver/requests/requests_test.go
@@ -130,7 +130,7 @@
 				ConesDroppedAuto: 0, LowCubes: 1, MiddleCubes: 1,
 				HighCubes: 2, CubesDropped: 1, LowCones: 1,
 				MiddleCones: 2, HighCones: 0, ConesDropped: 1, SuperchargedPieces: 0,
-				AvgCycle: 34, DockedAuto: true, EngagedAuto: true,
+				AvgCycle: 34, Mobility: false, DockedAuto: true, EngagedAuto: true,
 				BalanceAttemptAuto: false, Docked: false, Engaged: false,
 				BalanceAttempt: false, CollectedBy: "alex",
 			},
@@ -142,7 +142,7 @@
 				ConesDroppedAuto: 1, LowCubes: 0, MiddleCubes: 0,
 				HighCubes: 1, CubesDropped: 0, LowCones: 0,
 				MiddleCones: 2, HighCones: 1, ConesDropped: 1, SuperchargedPieces: 0,
-				AvgCycle: 53, DockedAuto: true, EngagedAuto: false,
+				AvgCycle: 53, Mobility: true, DockedAuto: true, EngagedAuto: false,
 				BalanceAttemptAuto: false, Docked: false, Engaged: false,
 				BalanceAttempt: true, CollectedBy: "bob",
 			},
@@ -215,7 +215,7 @@
 				ConesDroppedAuto: 0, LowCubes: 1, MiddleCubes: 1,
 				HighCubes: 2, CubesDropped: 1, LowCones: 1,
 				MiddleCones: 2, HighCones: 0, ConesDropped: 1, SuperchargedPieces: 0,
-				AvgCycle: 34, DockedAuto: true, EngagedAuto: false,
+				AvgCycle: 34, Mobility: false, DockedAuto: true, EngagedAuto: false,
 				BalanceAttemptAuto: false, Docked: false, Engaged: false,
 				BalanceAttempt: true, CollectedBy: "isaac",
 			},
@@ -227,7 +227,7 @@
 				ConesDroppedAuto: 1, LowCubes: 0, MiddleCubes: 0,
 				HighCubes: 1, CubesDropped: 0, LowCones: 0,
 				MiddleCones: 2, HighCones: 1, ConesDropped: 1, SuperchargedPieces: 0,
-				AvgCycle: 53, DockedAuto: false, EngagedAuto: false,
+				AvgCycle: 53, Mobility: false, DockedAuto: false, EngagedAuto: false,
 				BalanceAttemptAuto: true, Docked: false, Engaged: false,
 				BalanceAttempt: true, CollectedBy: "unknown",
 			},
@@ -256,7 +256,7 @@
 				ConesDroppedAuto: 0, LowCubes: 1, MiddleCubes: 1,
 				HighCubes: 2, CubesDropped: 1, LowCones: 1,
 				MiddleCones: 2, HighCones: 0, ConesDropped: 1, SuperchargedPieces: 0,
-				AvgCycle: 34, DockedAuto: true, EngagedAuto: false,
+				AvgCycle: 34, Mobility: false, DockedAuto: true, EngagedAuto: false,
 				BalanceAttemptAuto: false, Docked: false, Engaged: false,
 				BalanceAttempt: true, CollectedBy: "isaac",
 			},
@@ -268,7 +268,7 @@
 				ConesDroppedAuto: 1, LowCubes: 0, MiddleCubes: 0,
 				HighCubes: 1, CubesDropped: 0, LowCones: 0,
 				MiddleCones: 2, HighCones: 1, ConesDropped: 1, SuperchargedPieces: 0,
-				AvgCycle: 53, DockedAuto: false, EngagedAuto: false,
+				AvgCycle: 53, Mobility: false, DockedAuto: false, EngagedAuto: false,
 				BalanceAttemptAuto: true, Docked: false, Engaged: false,
 				BalanceAttempt: true, CollectedBy: "unknown",
 			},
@@ -336,6 +336,15 @@
 			},
 			{
 				ActionTaken: &submit_actions.ActionTypeT{
+					Type: submit_actions.ActionTypeMobilityAction,
+					Value: &submit_actions.MobilityActionT{
+						Mobility: true,
+					},
+				},
+				Timestamp: 2200,
+			},
+			{
+				ActionTaken: &submit_actions.ActionTypeT{
 					Type: submit_actions.ActionTypeAutoBalanceAction,
 					Value: &submit_actions.AutoBalanceActionT{
 						Docked:         true,
@@ -416,7 +425,7 @@
 		ConesDroppedAuto: 0, LowCubes: 0, MiddleCubes: 0,
 		HighCubes: 0, CubesDropped: 0, LowCones: 0,
 		MiddleCones: 0, HighCones: 1, ConesDropped: 0, SuperchargedPieces: 1,
-		AvgCycle: 950, DockedAuto: true, EngagedAuto: true,
+		AvgCycle: 950, Mobility: true, DockedAuto: true, EngagedAuto: true,
 		BalanceAttemptAuto: false, Docked: true, Engaged: false,
 		BalanceAttempt: true, CollectedBy: "katie",
 	}
diff --git a/scouting/www/entry/entry.component.ts b/scouting/www/entry/entry.component.ts
index b56948a..8992ed8 100644
--- a/scouting/www/entry/entry.component.ts
+++ b/scouting/www/entry/entry.component.ts
@@ -15,6 +15,7 @@
   ScoreLevel,
   SubmitActions,
   StartMatchAction,
+  MobilityAction,
   AutoBalanceAction,
   PickupObjectAction,
   PlaceObjectAction,
@@ -54,6 +55,11 @@
       position: number;
     }
   | {
+      type: 'mobilityAction';
+      timestamp?: number;
+      mobility: boolean;
+    }
+  | {
       type: 'autoBalanceAction';
       timestamp?: number;
       docked: boolean;
@@ -205,22 +211,18 @@
             startMatchActionOffset
           );
           break;
-
-        case 'pickupObjectAction':
-          const pickupObjectActionOffset =
-            PickupObjectAction.createPickupObjectAction(
-              builder,
-              action.objectType,
-              action.auto || false
-            );
+        case 'mobilityAction':
+          const mobilityActionOffset = MobilityAction.createMobilityAction(
+            builder,
+            action.mobility
+          );
           actionOffset = Action.createAction(
             builder,
             BigInt(action.timestamp || 0),
-            ActionType.PickupObjectAction,
-            pickupObjectActionOffset
+            ActionType.MobilityAction,
+            mobilityActionOffset
           );
           break;
-
         case 'autoBalanceAction':
           const autoBalanceActionOffset =
             AutoBalanceAction.createAutoBalanceAction(
@@ -237,6 +239,20 @@
           );
           break;
 
+        case 'pickupObjectAction':
+          const pickupObjectActionOffset =
+            PickupObjectAction.createPickupObjectAction(
+              builder,
+              action.objectType,
+              action.auto || false
+            );
+          actionOffset = Action.createAction(
+            builder,
+            BigInt(action.timestamp || 0),
+            ActionType.PickupObjectAction,
+            pickupObjectActionOffset
+          );
+          break;
         case 'placeObjectAction':
           const placeObjectActionOffset =
             PlaceObjectAction.createPlaceObjectAction(
diff --git a/scouting/www/entry/entry.ng.html b/scouting/www/entry/entry.ng.html
index 72c5717..98e427b 100644
--- a/scouting/www/entry/entry.ng.html
+++ b/scouting/www/entry/entry.ng.html
@@ -118,6 +118,13 @@
       >
         CUBE
       </button>
+      <button
+        *ngIf="autoPhase"
+        class="btn btn-light"
+        (click)="addAction({type: 'mobilityAction', mobility: true});"
+      >
+        Mobility
+      </button>
       <!-- 'Balancing' during auto. -->
       <div *ngIf="autoPhase" class="d-grid gap-2">
         <label>
@@ -192,6 +199,13 @@
       >
         LOW
       </button>
+      <button
+        *ngIf="autoPhase"
+        class="btn btn-light"
+        (click)="addAction({type: 'mobilityAction', mobility: true});"
+      >
+        Mobility
+      </button>
       <!-- Impossible to place supercharged pieces in auto. -->
       <div *ngIf="autoPhase == false" class="d-grid gap-2">
         <button
@@ -202,7 +216,7 @@
         </button>
       </div>
       <!-- 'Balancing' during auto. -->
-      <div *ngIf="autoPhase" class="d-grid gap-2">
+      <div *ngIf="autoPhase" class="d-grid gap-1">
         <label>
           <input #docked type="checkbox" />
           Docked