Change entry for 2024 scouting

Signed-off-by: Emily Markova <emily.markova@gmail.com>
Change-Id: I37ffab8a4e80628c0c50361a4c8ae69900c5b0b9
diff --git a/scouting/scouting_test.cy.js b/scouting/scouting_test.cy.js
index 7d5d75b..691d8fc 100644
--- a/scouting/scouting_test.cy.js
+++ b/scouting/scouting_test.cy.js
@@ -84,14 +84,14 @@
   cy.get('[type="radio"]').first().check();
   clickButton('Start Match');
 
-  // Pick and Place Cone in Auto.
-  clickButton('CONE');
-  clickButton('HIGH');
+  // Pick and Place Note in Auto.
+  clickButton('NOTE');
+  clickButton('AMP');
 
   // Pick and Place Cube in Teleop.
   clickButton('Start Teleop');
-  clickButton('CUBE');
-  clickButton('LOW');
+  clickButton('NOTE');
+  clickButton('AMP AMPLIFIED');
 
   // Robot dead and revive.
   clickButton('DEAD');
@@ -99,19 +99,19 @@
 
   // Endgame.
   clickButton('Endgame');
-  cy.contains(/Docked & Engaged/).click();
+  cy.contains(/Harmony/).click();
 
   clickButton('End Match');
   headerShouldBe(teamNumber + ' Review and Submit ');
   cy.get('#review_data li')
     .eq(0)
     .should('have.text', ' Started match at position 1 ');
-  cy.get('#review_data li').eq(1).should('have.text', ' Picked up kCone ');
+  cy.get('#review_data li').eq(1).should('have.text', 'Picked up Note');
   cy.get('#review_data li')
     .last()
     .should(
       'have.text',
-      ' Ended Match; docked: false, engaged: true, attempted to dock and engage: false '
+      ' Ended Match; park: false, onStage: false, harmony: true, trapNote: false '
     );
 
   clickButton('Submit');
@@ -264,8 +264,8 @@
     cy.get('[type="radio"]').first().check();
     clickButton('Start Match');
 
-    // Pick up cone.
-    clickButton('CONE');
+    // Pick up note.
+    clickButton('NOTE');
 
     // Undo that pick up.
     clickButton('UNDO');
@@ -274,8 +274,8 @@
     headerShouldBe('3990 Pickup ');
 
     // Check the same thing but for undoing place.
-    clickButton('CUBE');
-    clickButton('MID');
+    clickButton('NOTE');
+    clickButton('AMP');
     clickButton('UNDO');
     headerShouldBe('3990 Place ');
   });
diff --git a/scouting/webserver/requests/messages/submit_2024_actions.fbs b/scouting/webserver/requests/messages/submit_2024_actions.fbs
index 5cb3cbe..61e36bc 100644
--- a/scouting/webserver/requests/messages/submit_2024_actions.fbs
+++ b/scouting/webserver/requests/messages/submit_2024_actions.fbs
@@ -15,7 +15,9 @@
     mobility:bool (id:0);
 }
 
-table PenaltyAction {}
+table PenaltyAction {
+    penalties: int (id:0);
+}
 
 table PickupNoteAction {
     auto:bool (id:0);
diff --git a/scouting/webserver/requests/requests.go b/scouting/webserver/requests/requests.go
index 75b438b..31ad4e3 100644
--- a/scouting/webserver/requests/requests.go
+++ b/scouting/webserver/requests/requests.go
@@ -199,8 +199,7 @@
 }
 
 func (handler requestAllMatchesHandler) teamHasBeenDataScouted(key MatchAssemblyKey, teamNumber string) (bool, error) {
-	// TODO change this to reference 2024 stats
-	stats, err := handler.db.ReturnStats2023ForTeam(
+	stats, err := handler.db.ReturnStats2024ForTeam(
 		teamNumber, key.MatchNumber, key.SetNumber, key.CompLevel, false)
 	if err != nil {
 		return false, err
@@ -480,7 +479,7 @@
 		} else if action_type == submit_2024_actions.ActionTypePenaltyAction {
 			var penaltyAction submit_2024_actions.PenaltyAction
 			penaltyAction.Init(actionTable.Bytes, actionTable.Pos)
-			stat.Penalties += 1
+			stat.Penalties += penaltyAction.Penalties()
 
 		} else if action_type == submit_2024_actions.ActionTypePickupNoteAction {
 			var pick_up_action submit_2024_actions.PickupNoteAction
@@ -1165,12 +1164,12 @@
 
 	err = handler.db.AddToStats2024(stats)
 	if err != nil {
-		respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Failed to submit stats: ", stats, ": ", err))
+		respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Failed to submit stats2024: ", stats, ": ", err))
 		return
 	}
 
 	builder := flatbuffers.NewBuilder(50 * 1024)
-	builder.Finish((&SubmitActionsResponseT{}).Pack(builder))
+	builder.Finish((&Submit2024ActionsResponseT{}).Pack(builder))
 	w.Write(builder.FinishedBytes())
 }
 
diff --git a/scouting/webserver/requests/requests_test.go b/scouting/webserver/requests/requests_test.go
index 67244d3..eb5e904 100644
--- a/scouting/webserver/requests/requests_test.go
+++ b/scouting/webserver/requests/requests_test.go
@@ -131,30 +131,22 @@
 			},
 		},
 		// Pretend that we have some data scouting data.
-		stats2023: []db.Stats2023{
+		stats2024: []db.Stats2024{
 			{
-				TeamNumber: "5", MatchNumber: 1, SetNumber: 1,
-				CompLevel: "qm", StartingQuadrant: 3, LowCubesAuto: 10,
-				MiddleCubesAuto: 1, HighCubesAuto: 1, CubesDroppedAuto: 0,
-				LowConesAuto: 1, MiddleConesAuto: 2, HighConesAuto: 1,
-				ConesDroppedAuto: 0, LowCubes: 1, MiddleCubes: 1,
-				HighCubes: 2, CubesDropped: 1, LowCones: 1,
-				MiddleCones: 2, HighCones: 0, ConesDropped: 1, SuperchargedPieces: 0,
-				AvgCycle: 34, Mobility: false, DockedAuto: true, EngagedAuto: true,
-				BalanceAttemptAuto: false, Docked: false, Engaged: false,
-				BalanceAttempt: false, CollectedBy: "alex",
+				PreScouting: false, TeamNumber: "5",
+				MatchNumber: 1, SetNumber: 1, CompLevel: "qm", StartingQuadrant: 3,
+				SpeakerAuto: 2, AmpAuto: 4, NotesDroppedAuto: 1, MobilityAuto: true,
+				Speaker: 0, Amp: 1, SpeakerAmplified: 2, AmpAmplified: 1,
+				NotesDropped: 0, Penalties: 01, TrapNote: true, AvgCycle: 233,
+				Park: false, OnStage: true, Harmony: false, CollectedBy: "alex",
 			},
 			{
-				TeamNumber: "973", MatchNumber: 3, SetNumber: 1,
-				CompLevel: "qm", StartingQuadrant: 1, LowCubesAuto: 0,
-				MiddleCubesAuto: 1, HighCubesAuto: 1, CubesDroppedAuto: 2,
-				LowConesAuto: 0, MiddleConesAuto: 0, HighConesAuto: 0,
-				ConesDroppedAuto: 1, LowCubes: 0, MiddleCubes: 0,
-				HighCubes: 1, CubesDropped: 0, LowCones: 0,
-				MiddleCones: 2, HighCones: 1, ConesDropped: 1, SuperchargedPieces: 0,
-				AvgCycle: 53, Mobility: true, DockedAuto: true, EngagedAuto: false,
-				BalanceAttemptAuto: false, Docked: false, Engaged: false,
-				BalanceAttempt: true, CollectedBy: "bob",
+				PreScouting: false, TeamNumber: "973",
+				MatchNumber: 3, SetNumber: 1, CompLevel: "qm", StartingQuadrant: 1,
+				SpeakerAuto: 0, AmpAuto: 2, NotesDroppedAuto: 0, MobilityAuto: false,
+				Speaker: 0, Amp: 4, SpeakerAmplified: 3, AmpAmplified: 1,
+				NotesDropped: 0, Penalties: 1, TrapNote: true, AvgCycle: 120,
+				Park: true, OnStage: false, Harmony: false, CollectedBy: "bob",
 			},
 		},
 	}
@@ -416,8 +408,10 @@
 			},
 			{
 				ActionTaken: &submit_2024_actions.ActionTypeT{
-					Type:  submit_2024_actions.ActionTypePenaltyAction,
-					Value: &submit_2024_actions.PenaltyActionT{},
+					Type: submit_2024_actions.ActionTypePenaltyAction,
+					Value: &submit_2024_actions.PenaltyActionT{
+						Penalties: 5,
+					},
 				},
 				Timestamp: 2400,
 			},
@@ -485,7 +479,7 @@
 		MatchNumber: 3, SetNumber: 1, CompLevel: "quals", StartingQuadrant: 2,
 		SpeakerAuto: 0, AmpAuto: 1, NotesDroppedAuto: 1, MobilityAuto: true,
 		Speaker: 0, Amp: 0, SpeakerAmplified: 1, AmpAmplified: 1,
-		NotesDropped: 0, Penalties: 1, TrapNote: false, AvgCycle: 950,
+		NotesDropped: 0, Penalties: 5, TrapNote: false, AvgCycle: 950,
 		Park: false, OnStage: false, Harmony: true, CollectedBy: "",
 	}
 
diff --git a/scouting/www/BUILD b/scouting/www/BUILD
index 55e9a8f..a403bf3 100644
--- a/scouting/www/BUILD
+++ b/scouting/www/BUILD
@@ -29,12 +29,12 @@
     name = "static_files",
     app_files = ":app",
     pictures = [
-        "//third_party/y2023/field:pictures",
+        "//third_party/y2024/field:pictures",
     ],
     replace_prefixes = {
         "prod": "",
         "dev": "",
-        "third_party/y2023": "pictures",
+        "third_party/y2024": "pictures",
     },
     tags = [
         "no-remote-cache",
diff --git a/scouting/www/entry/BUILD b/scouting/www/entry/BUILD
index 2884f23..98b457b 100644
--- a/scouting/www/entry/BUILD
+++ b/scouting/www/entry/BUILD
@@ -12,7 +12,7 @@
         ":node_modules/@angular/forms",
         "//scouting/webserver/requests/messages:error_response_ts_fbs",
         "//scouting/webserver/requests/messages:request_all_matches_response_ts_fbs",
-        "//scouting/webserver/requests/messages:submit_actions_ts_fbs",
+        "//scouting/webserver/requests/messages:submit_2024_actions_ts_fbs",
         "//scouting/www/rpc",
         "@com_github_google_flatbuffers//ts:flatbuffers_ts",
     ],
diff --git a/scouting/www/entry/entry.component.css b/scouting/www/entry/entry.component.css
index 38e9072..246887c 100644
--- a/scouting/www/entry/entry.component.css
+++ b/scouting/www/entry/entry.component.css
@@ -11,15 +11,10 @@
   touch-action: manipulation;
 }
 
-#switchFldbtn {
-  width: 15%;
-  display: block;
-  margin: 0 auto;
-  box-shadow: 2px 2px 1px #ccc;
-  max-width: 105px;
-  text-align: center;
+.row ul div span {
+  padding: 0px;
 }
 
-.row ul div span {
+input label {
   padding: 0px;
 }
diff --git a/scouting/www/entry/entry.component.ts b/scouting/www/entry/entry.component.ts
index 5a93251..b3e1e92 100644
--- a/scouting/www/entry/entry.component.ts
+++ b/scouting/www/entry/entry.component.ts
@@ -11,19 +11,19 @@
 import {Builder, ByteBuffer} from 'flatbuffers';
 import {ErrorResponse} from '../../webserver/requests/messages/error_response_generated';
 import {
-  ObjectType,
-  ScoreLevel,
-  SubmitActions,
   StartMatchAction,
+  ScoreType,
+  StageType,
+  Submit2024Actions,
   MobilityAction,
-  AutoBalanceAction,
-  PickupObjectAction,
-  PlaceObjectAction,
+  PenaltyAction,
+  PickupNoteAction,
+  PlaceNoteAction,
   RobotDeathAction,
   EndMatchAction,
   ActionType,
   Action,
-} from '../../webserver/requests/messages/submit_actions_generated';
+} from '../../webserver/requests/messages/submit_2024_actions_generated';
 import {Match} from '../../webserver/requests/messages/request_all_matches_response_generated';
 import {MatchListRequestor} from '@org_frc971/scouting/www/rpc';
 
@@ -62,23 +62,14 @@
       mobility: boolean;
     }
   | {
-      type: 'autoBalanceAction';
+      type: 'pickupNoteAction';
       timestamp?: number;
-      docked: boolean;
-      engaged: boolean;
-      balanceAttempt: boolean;
-    }
-  | {
-      type: 'pickupObjectAction';
-      timestamp?: number;
-      objectType: ObjectType;
       auto?: boolean;
     }
   | {
-      type: 'placeObjectAction';
+      type: 'placeNoteAction';
       timestamp?: number;
-      objectType?: ObjectType;
-      scoreLevel: ScoreLevel;
+      scoreType: ScoreType;
       auto?: boolean;
     }
   | {
@@ -87,10 +78,14 @@
       robotOn: boolean;
     }
   | {
+      type: 'penaltyAction';
+      timestamp?: number;
+      penalties: number;
+    }
+  | {
       type: 'endMatchAction';
-      docked: boolean;
-      engaged: boolean;
-      balanceAttempt: boolean;
+      stageType: StageType;
+      trapNote: boolean;
       timestamp?: number;
     }
   | {
@@ -98,6 +93,12 @@
       // It is used for undoing purposes.
       type: 'endAutoPhase';
       timestamp?: number;
+    }
+  | {
+      // This is not a action that is submitted,
+      // It is used for undoing purposes.
+      type: 'endTeleopPhase';
+      timestamp?: number;
     };
 
 @Component({
@@ -110,8 +111,7 @@
   // of radio buttons.
   readonly COMP_LEVELS = COMP_LEVELS;
   readonly COMP_LEVEL_LABELS = COMP_LEVEL_LABELS;
-  readonly ObjectType = ObjectType;
-  readonly ScoreLevel = ScoreLevel;
+  readonly ScoreType = ScoreType;
 
   section: Section = 'Team Selection';
   @Input() matchNumber: number = 1;
@@ -127,10 +127,10 @@
   errorMessage: string = '';
   autoPhase: boolean = true;
   mobilityCompleted: boolean = false;
-  lastObject: ObjectType = null;
 
   preScouting: boolean = false;
   matchStartTimestamp: number = 0;
+  penalties: number = 0;
 
   teamSelectionIsValid = false;
 
@@ -192,6 +192,20 @@
     return false;
   }
 
+  addPenalty(): void {
+    this.penalties += 1;
+  }
+
+  removePenalty(): void {
+    if (this.penalties > 0) {
+      this.penalties -= 1;
+    }
+  }
+
+  addPenalties(): void {
+    this.addAction({type: 'penaltyAction', penalties: this.penalties});
+  }
+
   addAction(action: ActionT): void {
     if (action.type == 'startMatchAction') {
       // Unix nanosecond timestamp.
@@ -202,27 +216,17 @@
       action.timestamp = Date.now() * 1e6 - this.matchStartTimestamp;
     }
 
+    if (action.type == 'endMatchAction') {
+      // endMatchAction occurs at the same time as penaltyAction so add to its timestamp to make it unique.
+      action.timestamp += 1;
+    }
+
     if (action.type == 'mobilityAction') {
       this.mobilityCompleted = true;
     }
 
-    if (action.type == 'autoBalanceAction') {
-      // Timestamp is a unique index in the database so
-      // adding one makes sure it dosen't overlap with the
-      // start teleop action that is added at the same time.
-      action.timestamp += 1;
-    }
-
-    if (
-      action.type == 'pickupObjectAction' ||
-      action.type == 'placeObjectAction'
-    ) {
+    if (action.type == 'pickupNoteAction' || action.type == 'placeNoteAction') {
       action.auto = this.autoPhase;
-      if (action.type == 'pickupObjectAction') {
-        this.lastObject = action.objectType;
-      } else if (action.type == 'placeObjectAction') {
-        action.objectType = this.lastObject;
-      }
     }
     this.actionList.push(action);
   }
@@ -233,14 +237,23 @@
       switch (lastAction?.type) {
         case 'endAutoPhase':
           this.autoPhase = true;
-        case 'pickupObjectAction':
+          this.section = 'Pickup';
+        case 'pickupNoteAction':
           this.section = 'Pickup';
           break;
-        case 'placeObjectAction':
+        case 'endTeleopPhase':
+          this.section = 'Pickup';
+          break;
+        case 'placeNoteAction':
           this.section = 'Place';
           break;
         case 'endMatchAction':
-          this.section = 'Pickup';
+          this.section = 'Endgame';
+        case 'mobilityAction':
+          this.mobilityCompleted = false;
+          break;
+        case 'startMatchAction':
+          this.section = 'Init';
           break;
         case 'robotDeathAction':
           // TODO(FILIP): Return user to the screen they
@@ -254,12 +267,12 @@
     }
   }
 
-  stringifyObjectType(objectType: ObjectType): String {
-    return ObjectType[objectType];
+  stringifyScoreType(scoreType: ScoreType): String {
+    return ScoreType[scoreType];
   }
 
-  stringifyScoreLevel(scoreLevel: ScoreLevel): String {
-    return ScoreLevel[scoreLevel];
+  stringifyStageType(stageType: StageType): String {
+    return StageType[stageType];
   }
 
   changeSectionTo(target: Section) {
@@ -276,7 +289,7 @@
     this.header.nativeElement.scrollIntoView();
   }
 
-  async submitActions() {
+  async submit2024Actions() {
     const builder = new Builder();
     const actionOffsets: number[] = [];
 
@@ -307,49 +320,42 @@
             mobilityActionOffset
           );
           break;
-        case 'autoBalanceAction':
-          const autoBalanceActionOffset =
-            AutoBalanceAction.createAutoBalanceAction(
-              builder,
-              action.docked,
-              action.engaged,
-              action.balanceAttempt
-            );
+        case 'penaltyAction':
+          const penaltyActionOffset = PenaltyAction.createPenaltyAction(
+            builder,
+            action.penalties
+          );
           actionOffset = Action.createAction(
             builder,
             BigInt(action.timestamp || 0),
-            ActionType.AutoBalanceAction,
-            autoBalanceActionOffset
+            ActionType.PenaltyAction,
+            penaltyActionOffset
           );
           break;
-
-        case 'pickupObjectAction':
-          const pickupObjectActionOffset =
-            PickupObjectAction.createPickupObjectAction(
+        case 'pickupNoteAction':
+          const pickupNoteActionOffset =
+            PickupNoteAction.createPickupNoteAction(
               builder,
-              action.objectType,
               action.auto || false
             );
           actionOffset = Action.createAction(
             builder,
             BigInt(action.timestamp || 0),
-            ActionType.PickupObjectAction,
-            pickupObjectActionOffset
+            ActionType.PickupNoteAction,
+            pickupNoteActionOffset
           );
           break;
-        case 'placeObjectAction':
-          const placeObjectActionOffset =
-            PlaceObjectAction.createPlaceObjectAction(
-              builder,
-              action.objectType,
-              action.scoreLevel,
-              action.auto || false
-            );
+        case 'placeNoteAction':
+          const placeNoteActionOffset = PlaceNoteAction.createPlaceNoteAction(
+            builder,
+            action.scoreType,
+            action.auto || false
+          );
           actionOffset = Action.createAction(
             builder,
             BigInt(action.timestamp || 0),
-            ActionType.PlaceObjectAction,
-            placeObjectActionOffset
+            ActionType.PlaceNoteAction,
+            placeNoteActionOffset
           );
           break;
 
@@ -367,9 +373,8 @@
         case 'endMatchAction':
           const endMatchActionOffset = EndMatchAction.createEndMatchAction(
             builder,
-            action.docked,
-            action.engaged,
-            action.balanceAttempt
+            action.stageType,
+            action.trapNote
           );
           actionOffset = Action.createAction(
             builder,
@@ -383,6 +388,10 @@
           // Not important action.
           break;
 
+        case 'endTeleopPhase':
+          // Not important action.
+          break;
+
         default:
           throw new Error(`Unknown action type`);
       }
@@ -394,21 +403,21 @@
     const teamNumberFb = builder.createString(this.teamNumber);
     const compLevelFb = builder.createString(this.compLevel);
 
-    const actionsVector = SubmitActions.createActionsListVector(
+    const actionsVector = Submit2024Actions.createActionsListVector(
       builder,
       actionOffsets
     );
-    SubmitActions.startSubmitActions(builder);
-    SubmitActions.addTeamNumber(builder, teamNumberFb);
-    SubmitActions.addMatchNumber(builder, this.matchNumber);
-    SubmitActions.addSetNumber(builder, this.setNumber);
-    SubmitActions.addCompLevel(builder, compLevelFb);
-    SubmitActions.addActionsList(builder, actionsVector);
-    SubmitActions.addPreScouting(builder, this.preScouting);
-    builder.finish(SubmitActions.endSubmitActions(builder));
+    Submit2024Actions.startSubmit2024Actions(builder);
+    Submit2024Actions.addTeamNumber(builder, teamNumberFb);
+    Submit2024Actions.addMatchNumber(builder, this.matchNumber);
+    Submit2024Actions.addSetNumber(builder, this.setNumber);
+    Submit2024Actions.addCompLevel(builder, compLevelFb);
+    Submit2024Actions.addActionsList(builder, actionsVector);
+    Submit2024Actions.addPreScouting(builder, this.preScouting);
+    builder.finish(Submit2024Actions.endSubmit2024Actions(builder));
 
     const buffer = builder.asUint8Array();
-    const res = await fetch('/requests/submit/submit_actions', {
+    const res = await fetch('/requests/submit/submit_2024_actions', {
       method: 'POST',
       body: buffer,
     });
diff --git a/scouting/www/entry/entry.ng.html b/scouting/www/entry/entry.ng.html
index 43575cd..9490237 100644
--- a/scouting/www/entry/entry.ng.html
+++ b/scouting/www/entry/entry.ng.html
@@ -81,7 +81,7 @@
     <h2>Select Starting Position</h2>
     <img
       id="field_starting_positions_image"
-      src="/sha256/b71def525fb78486617a8b350c0ba6907e8ea25f78d4084a932cba8ae922528c/pictures/field/field.jpg"
+      src="/sha256/bb83d2c976c1496bb470371821d1d1882d6baf31178009a6f6cba579880c6a03/pictures/field/2024_field.png"
       alt="Starting Positions Image"
       class="img-fluid"
     />
@@ -129,15 +129,9 @@
       </button>
       <button
         class="btn btn-warning"
-        (click)="changeSectionTo('Place'); addAction({type: 'pickupObjectAction', objectType: ObjectType.kCone});"
+        (click)="changeSectionTo('Place'); addAction({type: 'pickupNoteAction'});"
       >
-        CONE
-      </button>
-      <button
-        class="btn btn-primary"
-        (click)="changeSectionTo('Place'); addAction({type: 'pickupObjectAction', objectType: ObjectType.kCube});"
-      >
-        CUBE
+        NOTE
       </button>
       <button
         *ngIf="autoPhase && !mobilityCompleted"
@@ -146,49 +140,35 @@
       >
         Mobility
       </button>
-      <!-- 'Balancing' during auto. -->
-      <div *ngIf="autoPhase" class="d-grid gap-2">
-        <label>
-          <input
-            #docked
-            type="radio"
-            id="option1"
-            name="docked_engaged"
-            value="docked"
-          />
-          Docked (on the charging station)
-        </label>
-        <label>
-          <input
-            #engaged
-            type="radio"
-            id="option2"
-            name="docked_engaged"
-            value="dockedengaged"
-          />
-          Docked &amp; Engaged (level &amp; station lights on)
-        </label>
-        <label>
-          <input
-            #attempted
-            type="radio"
-            id="option3"
-            name="docked_engaged"
-            value="failed"
-          />
-          Attempted to dock and engage but failed
-        </label>
+      <div style="display: flex">
+        <h5>Penalties :</h5>
         <button
-          class="btn btn-dark"
-          (click)="autoPhase = false; addAction({type: 'endAutoPhase'}); addAction({type: 'autoBalanceAction', docked: docked.checked, engaged: engaged.checked, balanceAttempt: attempted.checked});"
+          class="btn-light"
+          style="width: 40px; margin-right: 15px"
+          (click)="removePenalty()"
         >
-          Start Teleop
+          -
+        </button>
+        <p>{{this.penalties}}</p>
+        <button
+          class="btn-light"
+          style="width: 40px; margin-left: 15px"
+          (click)="addPenalty()"
+        >
+          +
         </button>
       </div>
       <button
+        *ngIf="autoPhase"
+        class="btn btn-dark"
+        (click)="autoPhase = false; addAction({type: 'endAutoPhase'});"
+      >
+        Start Teleop
+      </button>
+      <button
         *ngIf="!autoPhase"
         class="btn btn-info"
-        (click)="changeSectionTo('Endgame')"
+        (click)="changeSectionTo('Endgame'); addAction({type: 'endTeleopPhase'});"
       >
         Endgame
       </button>
@@ -212,23 +192,62 @@
       >
         DEAD
       </button>
+      <div *ngIf="!autoPhase" class="d-grid gap-1" style="padding: 0">
+        <div
+          style="
+            display: flex-wrap;
+            padding: 0;
+            justify-content: center;
+            text-align: center;
+            align-content: center;
+            margin: 0;
+          "
+        >
+          <button
+            class="btn btn-success"
+            (click)="changeSectionTo('Pickup'); addAction({type: 'placeNoteAction', scoreType: ScoreType.kAMP});"
+            style="width: 48%; height: 12vh; margin: 0px 10px 10px 0px"
+          >
+            AMP
+          </button>
+
+          <button
+            class="btn btn-warning"
+            (click)="changeSectionTo('Pickup');  addAction({type: 'placeNoteAction', scoreType: ScoreType.kAMP_AMPLIFIED});"
+            style="width: 48%; height: 12vh; margin: 0px 0px 10px 0px"
+          >
+            AMP AMPLIFIED
+          </button>
+          <button
+            class="btn btn-success"
+            (click)="changeSectionTo('Pickup'); addAction({type: 'placeNoteAction', scoreType: ScoreType.kSPEAKER});"
+            style="width: 48%; height: 12vh; margin: 0px 10px 0px 0px"
+          >
+            SPEAKER
+          </button>
+          <button
+            class="btn btn-warning"
+            (click)="changeSectionTo('Pickup');  addAction({type: 'placeNoteAction', scoreType: ScoreType.kSPEAKER_AMPLIFIED});"
+            style="width: 48%; height: 12vh; margin: 0px 0px 0px 0px"
+          >
+            SPEAKER AMPLIFIED
+          </button>
+        </div>
+      </div>
+
       <button
+        *ngIf="autoPhase"
         class="btn btn-success"
-        (click)="changeSectionTo('Pickup'); addAction({type: 'placeObjectAction', scoreLevel: ScoreLevel.kHigh});"
+        (click)="changeSectionTo('Pickup'); addAction({type: 'placeNoteAction', scoreType: ScoreType.kAMP});"
       >
-        HIGH
+        AMP
       </button>
       <button
+        *ngIf="autoPhase"
         class="btn btn-warning"
-        (click)="changeSectionTo('Pickup'); addAction({type: 'placeObjectAction', scoreLevel: ScoreLevel.kMiddle});"
+        (click)="changeSectionTo('Pickup'); addAction({type: 'placeNoteAction', scoreType: ScoreType.kSPEAKER});"
       >
-        MID
-      </button>
-      <button
-        class="btn btn-danger"
-        (click)="changeSectionTo('Pickup'); addAction({type: 'placeObjectAction', scoreLevel: ScoreLevel.kLow});"
-      >
-        LOW
+        SPEAKER
       </button>
       <button
         *ngIf="autoPhase && !mobilityCompleted"
@@ -237,58 +256,35 @@
       >
         Mobility
       </button>
-      <!-- Impossible to place supercharged pieces in auto. -->
-      <div *ngIf="autoPhase == false" class="d-grid gap-2">
+      <div style="display: flex">
+        <h5>Penalties :</h5>
         <button
-          class="btn btn-dark"
-          (click)="changeSectionTo('Pickup'); addAction({type: 'placeObjectAction', scoreLevel: ScoreLevel.kSupercharged});"
+          class="btn-light"
+          style="width: 40px; margin-right: 15px"
+          (click)="removePenalty()"
         >
-          SUPERCHARGED
+          -
         </button>
-      </div>
-      <!-- 'Balancing' during auto. -->
-      <div *ngIf="autoPhase" class="d-grid gap-1">
-        <label>
-          <input
-            #docked
-            type="radio"
-            id="option1"
-            name="docked_engaged"
-            value="docked"
-          />
-          Docked (on the charging station)
-        </label>
-        <label>
-          <input
-            #engaged
-            type="radio"
-            id="option2"
-            name="docked_engaged"
-            value="dockedengaged"
-          />
-          Docked &amp; Engaged (level &amp; station lights on)
-        </label>
-        <label>
-          <input
-            #attempted
-            type="radio"
-            id="option3"
-            name="docked_engaged"
-            value="failed"
-          />
-          Attempted to dock and engage but failed
-        </label>
+        <p>{{this.penalties}}</p>
         <button
-          class="btn btn-dark"
-          (click)="autoPhase = false; addAction({type: 'endAutoPhase'}); addAction({type: 'autoBalanceAction', docked: docked.checked, engaged: engaged.checked, balanceAttempt: attempted.checked});"
+          class="btn-light"
+          style="width: 40px; margin-left: 15px"
+          (click)="addPenalty()"
         >
-          Start Teleop
+          +
         </button>
       </div>
       <button
+        class="btn btn-dark"
+        *ngIf="autoPhase"
+        (click)="autoPhase = false; addAction({type: 'endAutoPhase'});"
+      >
+        Start Teleop
+      </button>
+      <button
         *ngIf="!autoPhase"
         class="btn btn-info"
-        (click)="changeSectionTo('Endgame')"
+        (click)="changeSectionTo('Endgame'); addAction({type: 'endTeleopPhase'});"
       >
         Endgame
       </button>
@@ -298,7 +294,7 @@
     <h6 class="text-muted">
       Last Action: {{actionList[actionList.length - 1].type}}
     </h6>
-    <div class="d-grid gap-5">
+    <div class="d-grid gap-4">
       <button class="btn btn-secondary" (click)="undoLastAction()">UNDO</button>
       <button
         class="btn btn-danger"
@@ -306,40 +302,68 @@
       >
         DEAD
       </button>
-      <label>
+      <label style="padding: 0">
         <input
-          #docked
+          #park
           type="radio"
           id="option1"
-          name="docked_engaged"
-          value="docked"
+          name="endgameaction"
+          value="park"
         />
-        Docked (on the charging station)
+        Park
       </label>
-      <label>
+      <label style="padding: 0">
         <input
-          #engaged
+          #onStage
           type="radio"
           id="option2"
-          name="docked_engaged"
-          value="dockedengaged"
+          name="endgameaction"
+          value="onStage"
         />
-        Docked &amp; Engaged (level &amp; station lights on)
+        On Stage
       </label>
-      <label>
+      <label style="padding: 0">
         <input
-          #attempted
+          #harmony
           type="radio"
           id="option3"
-          name="docked_engaged"
-          value="failed"
+          name="endgameaction"
+          value="harmony"
         />
-        Attempted to dock and engage but failed
+        Harmony
       </label>
+      <label style="padding: 0">
+        <input
+          #trapNote
+          type="checkbox"
+          id="trapnote"
+          name="trapnote"
+          value="trapNote"
+        />
+        Trap Note
+      </label>
+      <div style="display: flex">
+        <h5>Penalties :</h5>
+        <button
+          class="btn-light"
+          style="width: 40px; margin-right: 15px"
+          (click)="removePenalty()"
+        >
+          -
+        </button>
+        <p>{{this.penalties}}</p>
+        <button
+          class="btn-light"
+          style="width: 40px; margin-left: 15px"
+          (click)="addPenalty()"
+        >
+          +
+        </button>
+      </div>
       <button
         *ngIf="!autoPhase"
         class="btn btn-info"
-        (click)="changeSectionTo('Review and Submit'); addAction({type: 'endMatchAction', docked: docked.checked, engaged: engaged.checked, balanceAttempt: attempted.checked});"
+        (click)="changeSectionTo('Review and Submit');  addPenalties(); addAction({type: 'endMatchAction', park: park.checked, onStage: onStage.checked, harmony: harmony.checked, trapNote: trapNote.checked});"
       >
         End Match
       </button>
@@ -354,12 +378,6 @@
       >
         Revive
       </button>
-      <button
-        class="btn btn-info"
-        (click)="changeSectionTo('Review and Submit'); addAction({type: 'endMatchAction', docked: docked.checked, engaged: engaged.checked});"
-      >
-        End Match
-      </button>
     </div>
   </div>
   <div *ngSwitchCase="'Review and Submit'" id="Review" class="container-fluid">
@@ -374,21 +392,14 @@
             <span *ngSwitchCase="'startMatchAction'">
               Started match at position {{action.position}}
             </span>
-            <span *ngSwitchCase="'pickupObjectAction'">
-              Picked up {{stringifyObjectType(action.objectType)}}
-            </span>
-            <span *ngSwitchCase="'placeObjectAction'">
-              Placed at {{stringifyScoreLevel(action.scoreLevel)}}
-            </span>
-            <span *ngSwitchCase="'autoBalanceAction'">
-              Docked: {{action.docked}}, engaged: {{action.engaged}}, attempted
-              to balance and engage: {{action.balanceAttempt}}
+            <span *ngSwitchCase="'pickupNoteAction'">Picked up Note</span>
+            <span *ngSwitchCase="'placeNoteAction'">
+              Placed at {{stringifyScoreType(action.scoreType)}}
             </span>
             <span *ngSwitchCase="'endAutoPhase'">Ended auto phase</span>
             <span *ngSwitchCase="'endMatchAction'">
-              Ended Match; docked: {{action.docked}}, engaged:
-              {{action.engaged}}, attempted to dock and engage:
-              {{action.balanceAttempt}}
+              Ended Match; park: {{action.park}}, onStage: {{action.onStage}},
+              harmony: {{action.harmony}}, trapNote: {{action.trapNote}}
             </span>
             <span *ngSwitchCase="'robotDeathAction'">
               Robot on: {{action.robotOn}}
@@ -397,13 +408,18 @@
               Mobility: {{action.mobility}}
             </span>
             <span *ngSwitchDefault>{{action.type}}</span>
+            <span *ngSwitchCase="'penaltyAction'">
+              Penalties: {{action.penalties}}
+            </span>
           </div>
         </li>
       </ul>
     </div>
     <div class="d-grid gap-5">
       <button class="btn btn-secondary" (click)="undoLastAction()">UNDO</button>
-      <button class="btn btn-warning" (click)="submitActions();">Submit</button>
+      <button class="btn btn-warning" (click)="submit2024Actions();">
+        Submit
+      </button>
     </div>
   </div>
   <div *ngSwitchCase="'Success'" id="Success" class="container-fluid">
diff --git a/scouting/www/pit_scouting/pit_scouting.component.ts b/scouting/www/pit_scouting/pit_scouting.component.ts
index 58e7647..7bb884c 100644
--- a/scouting/www/pit_scouting/pit_scouting.component.ts
+++ b/scouting/www/pit_scouting/pit_scouting.component.ts
@@ -57,6 +57,8 @@
     const builder = new Builder();
     const teamNumber = builder.createString(this.teamNumber);
     const pitImage = builder.createString(
+      // Remove anything between /s in order to end up with only the file name.
+      // Example : path/to/file.txt -> file.txt
       this.pitImage.toString().replace(/^.*[\\\/]/, '')
     );
     const imageData = SubmitPitImage.createImageDataVector(
diff --git a/scouting/www/rpc/BUILD b/scouting/www/rpc/BUILD
index ab28581..d1367ea 100644
--- a/scouting/www/rpc/BUILD
+++ b/scouting/www/rpc/BUILD
@@ -11,8 +11,8 @@
     generate_public_api = False,
     deps = [
         "//scouting/webserver/requests/messages:error_response_ts_fbs",
-        "//scouting/webserver/requests/messages:request_2023_data_scouting_response_ts_fbs",
-        "//scouting/webserver/requests/messages:request_2023_data_scouting_ts_fbs",
+        "//scouting/webserver/requests/messages:request_2024_data_scouting_response_ts_fbs",
+        "//scouting/webserver/requests/messages:request_2024_data_scouting_ts_fbs",
         "//scouting/webserver/requests/messages:request_all_driver_rankings_response_ts_fbs",
         "//scouting/webserver/requests/messages:request_all_driver_rankings_ts_fbs",
         "//scouting/webserver/requests/messages:request_all_matches_response_ts_fbs",
diff --git a/scouting/www/rpc/view_data_requestor.ts b/scouting/www/rpc/view_data_requestor.ts
index f1f2b79..74fc212 100644
--- a/scouting/www/rpc/view_data_requestor.ts
+++ b/scouting/www/rpc/view_data_requestor.ts
@@ -11,16 +11,16 @@
   Ranking,
   RequestAllDriverRankingsResponse,
 } from '../../webserver/requests/messages/request_all_driver_rankings_response_generated';
-import {Request2023DataScouting} from '../../webserver/requests/messages/request_2023_data_scouting_generated';
+import {Request2024DataScouting} from '../../webserver/requests/messages/request_2024_data_scouting_generated';
 import {
   PitImage,
   RequestAllPitImagesResponse,
 } from '../../webserver/requests/messages/request_all_pit_images_response_generated';
 import {RequestAllPitImages} from '../../webserver/requests/messages/request_all_pit_images_generated';
 import {
-  Stats2023,
-  Request2023DataScoutingResponse,
-} from '../../webserver/requests/messages/request_2023_data_scouting_response_generated';
+  Stats2024,
+  Request2024DataScoutingResponse,
+} from '../../webserver/requests/messages/request_2024_data_scouting_response_generated';
 
 @Injectable({providedIn: 'root'})
 export class ViewDataRequestor {
@@ -82,15 +82,15 @@
     return driverRankingList;
   }
   // Returns all data scouting entries from the database.
-  async fetchStats2023List(): Promise<Stats2023[]> {
+  async fetchStats2024List(): Promise<Stats2024[]> {
     let fbBuffer = await this.fetchFromServer(
-      Request2023DataScouting.startRequest2023DataScouting,
-      Request2023DataScouting.endRequest2023DataScouting,
-      '/requests/request/2023_data_scouting'
+      Request2024DataScouting.startRequest2024DataScouting,
+      Request2024DataScouting.endRequest2024DataScouting,
+      '/requests/request/2024_data_scouting'
     );
 
     const parsedResponse =
-      Request2023DataScoutingResponse.getRootAsRequest2023DataScoutingResponse(
+      Request2024DataScoutingResponse.getRootAsRequest2024DataScoutingResponse(
         fbBuffer
       );
 
diff --git a/scouting/www/view/BUILD b/scouting/www/view/BUILD
index 67c7e3b..738ea00 100644
--- a/scouting/www/view/BUILD
+++ b/scouting/www/view/BUILD
@@ -10,11 +10,11 @@
     ],
     deps = [
         ":node_modules/@angular/forms",
-        "//scouting/webserver/requests/messages:delete_2023_data_scouting_response_ts_fbs",
-        "//scouting/webserver/requests/messages:delete_2023_data_scouting_ts_fbs",
+        "//scouting/webserver/requests/messages:delete_2024_data_scouting_response_ts_fbs",
+        "//scouting/webserver/requests/messages:delete_2024_data_scouting_ts_fbs",
         "//scouting/webserver/requests/messages:error_response_ts_fbs",
-        "//scouting/webserver/requests/messages:request_2023_data_scouting_response_ts_fbs",
-        "//scouting/webserver/requests/messages:request_2023_data_scouting_ts_fbs",
+        "//scouting/webserver/requests/messages:request_2024_data_scouting_response_ts_fbs",
+        "//scouting/webserver/requests/messages:request_2024_data_scouting_ts_fbs",
         "//scouting/webserver/requests/messages:request_all_driver_rankings_response_ts_fbs",
         "//scouting/webserver/requests/messages:request_all_driver_rankings_ts_fbs",
         "//scouting/webserver/requests/messages:request_all_notes_response_ts_fbs",
diff --git a/scouting/www/view/view.component.ts b/scouting/www/view/view.component.ts
index 64b0680..ea9a61f 100644
--- a/scouting/www/view/view.component.ts
+++ b/scouting/www/view/view.component.ts
@@ -6,9 +6,9 @@
   RequestAllDriverRankingsResponse,
 } from '../../webserver/requests/messages/request_all_driver_rankings_response_generated';
 import {
-  Stats2023,
-  Request2023DataScoutingResponse,
-} from '../../webserver/requests/messages/request_2023_data_scouting_response_generated';
+  Stats2024,
+  Request2024DataScoutingResponse,
+} from '../../webserver/requests/messages/request_2024_data_scouting_response_generated';
 
 import {
   PitImage,
@@ -19,12 +19,12 @@
   Note,
   RequestAllNotesResponse,
 } from '../../webserver/requests/messages/request_all_notes_response_generated';
-import {Delete2023DataScouting} from '../../webserver/requests/messages/delete_2023_data_scouting_generated';
-import {Delete2023DataScoutingResponse} from '../../webserver/requests/messages/delete_2023_data_scouting_response_generated';
+import {Delete2024DataScouting} from '../../webserver/requests/messages/delete_2024_data_scouting_generated';
+import {Delete2024DataScoutingResponse} from '../../webserver/requests/messages/delete_2024_data_scouting_response_generated';
 
 import {ViewDataRequestor} from '../rpc';
 
-type Source = 'Notes' | 'Stats2023' | 'PitImages' | 'DriverRanking';
+type Source = 'Notes' | 'Stats2024' | 'PitImages' | 'DriverRanking';
 
 //TODO(Filip): Deduplicate
 const COMP_LEVEL_LABELS = {
@@ -63,7 +63,7 @@
   noteList: Note[] = [];
   driverRankingList: Ranking[] = [];
   pitImageList: PitImage[][] = [];
-  statList: Stats2023[] = [];
+  statList: Stats2024[] = [];
 
   // Fetch notes on initialization.
   ngOnInit() {
@@ -123,8 +123,8 @@
         this.fetchNotes();
       }
 
-      case 'Stats2023': {
-        this.fetchStats2023();
+      case 'Stats2024': {
+        this.fetchStats2024();
       }
 
       case 'PitImages': {
@@ -162,7 +162,7 @@
   }
 
   // Gets called when a user clicks the delete icon.
-  async deleteDataScouting(
+  async delete2024DataScouting(
     compLevel: string,
     matchNumber: number,
     setNumber: number,
@@ -172,17 +172,17 @@
       'block_alerts'
     ) as HTMLInputElement;
     if (block_alerts.checked || window.confirm('Actually delete data?')) {
-      await this.requestDeleteDataScouting(
+      await this.requestDelete2024DataScouting(
         compLevel,
         matchNumber,
         setNumber,
         teamNumber
       );
-      await this.fetchStats2023();
+      await this.fetchStats2024();
     }
   }
 
-  async requestDeleteDataScouting(
+  async requestDelete2024DataScouting(
     compLevel: string,
     matchNumber: number,
     setNumber: number,
@@ -194,7 +194,7 @@
     const teamNumberData = builder.createString(teamNumber);
 
     builder.finish(
-      Delete2023DataScouting.createDelete2023DataScouting(
+      Delete2024DataScouting.createDelete2024DataScouting(
         builder,
         compLevelData,
         matchNumber,
@@ -204,7 +204,7 @@
     );
 
     const buffer = builder.asUint8Array();
-    const res = await fetch('/requests/delete/delete_2023_data_scouting', {
+    const res = await fetch('/requests/delete/delete_2024_data_scouting', {
       method: 'POST',
       body: buffer,
     });
@@ -270,12 +270,12 @@
   }
 
   // Fetch all data scouting (stats) data and store in statList.
-  async fetchStats2023() {
+  async fetchStats2024() {
     this.progressMessage = 'Fetching stats list. Please be patient.';
     this.errorMessage = '';
 
     try {
-      this.statList = await this.viewDataRequestor.fetchStats2023List();
+      this.statList = await this.viewDataRequestor.fetchStats2024List();
       this.progressMessage = 'Successfully fetched stats list.';
     } catch (e) {
       this.errorMessage = e;
diff --git a/scouting/www/view/view.ng.html b/scouting/www/view/view.ng.html
index 239548c..14e8c8a 100644
--- a/scouting/www/view/view.ng.html
+++ b/scouting/www/view/view.ng.html
@@ -24,10 +24,10 @@
       <a
         class="dropdown-item"
         href="#"
-        (click)="switchDataSource('Stats2023')"
+        (click)="switchDataSource('Stats2024')"
         id="stats_source_dropdown"
       >
-        Stats
+        Stats2024
       </a>
     </li>
     <li>
@@ -93,8 +93,8 @@
       </tbody>
     </table>
   </div>
-  <!-- Stats Data Display. -->
-  <div *ngSwitchCase="'Stats2023'">
+  <!-- Stats2024 Data Display. -->
+  <div *ngSwitchCase="'Stats2024'">
     <table class="table">
       <thead>
         <tr>
@@ -114,17 +114,17 @@
         </tr>
       </thead>
       <tbody>
-        <tr *ngFor="let stat2023 of statList; index as i;">
-          <th scope="row">{{stat2023.matchNumber()}}</th>
-          <td>{{stat2023.teamNumber()}}</td>
-          <td>{{COMP_LEVEL_LABELS[stat2023.compLevel()]}}</td>
-          <td>{{stat2023.collectedBy()}}</td>
+        <tr *ngFor="let stat2024 of statList; index as i;">
+          <th scope="row">{{stat2024.matchNumber()}}</th>
+          <td>{{stat2024.teamNumber()}}</td>
+          <td>{{COMP_LEVEL_LABELS[stat2024.compLevel()]}}</td>
+          <td>{{stat2024.collectedBy()}}</td>
           <!-- Delete Icon. -->
           <td>
             <button
               class="btn btn-danger"
               id="delete_button_{{i}}"
-              (click)="deleteDataScouting(stat2023.compLevel(), stat2023.matchNumber(), stat2023.setNumber(), stat2023.teamNumber())"
+              (click)="delete2024DataScouting(stat2024.compLevel(), stat2024.matchNumber(), stat2024.setNumber(), stat2024.teamNumber())"
             >
               <i class="bi bi-trash"></i>
             </button>