| <div class="header" #header> |
| <h2> |
| <span *ngIf="section != 'Team Selection'">{{teamNumber}}</span> |
| {{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" |
| (ngModelChange)="updateTeamSelectionValidity()" |
| type="number" |
| id="match_number" |
| min="1" |
| max="999" |
| /> |
| </div> |
| <div class="row"> |
| <label for="team_number">Team Number</label> |
| <input |
| [(ngModel)]="teamNumber" |
| (ngModelChange)="updateTeamSelectionValidity()" |
| type="text" |
| id="team_number" |
| /> |
| </div> |
| <div class="row"> |
| <label for="set_number">Set Number</label> |
| <input |
| [(ngModel)]="setNumber" |
| (ngModelChange)="updateTeamSelectionValidity()" |
| type="number" |
| id="set_number" |
| min="1" |
| max="10" |
| /> |
| </div> |
| <div class="row"> |
| <label for="comp_level">Comp Level</label> |
| <select |
| [(ngModel)]="compLevel" |
| (ngModelChange)="updateTeamSelectionValidity()" |
| type="number" |
| id="comp_level" |
| > |
| <option *ngFor="let level of COMP_LEVELS" [ngValue]="level"> |
| {{COMP_LEVEL_LABELS[level]}} |
| </option> |
| </select> |
| </div> |
| <div class="row"> |
| <label> |
| <input |
| id="pre_scouting" |
| name="comp_type" |
| type="radio" |
| [(ngModel)]="compType" |
| value="Prescouting" |
| (ngModelChange)="updateTeamSelectionValidity()" |
| /> |
| Pre-scouting |
| </label> |
| </div> |
| <div class="row"> |
| <label> |
| <input |
| id="practice_match" |
| name="comp_type" |
| type="radio" |
| [(ngModel)]="compType" |
| value="Practice" |
| (ngModelChange)="updateTeamSelectionValidity()" |
| /> |
| Practice Match |
| </label> |
| </div> |
| <div class="buttons"> |
| <!-- hack to right align the next button --> |
| <div></div> |
| <button |
| class="btn btn-primary" |
| (click)="changeSectionTo('Init');" |
| [disabled]="!teamSelectionIsValid" |
| > |
| Next |
| </button> |
| </div> |
| </div> |
| <div *ngSwitchCase="'Init'" id="init" class="container-fluid"> |
| <h2>Select Starting Position</h2> |
| <img |
| id="field_starting_positions_image" |
| src="/sha256/bb83d2c976c1496bb470371821d1d1882d6baf31178009a6f6cba579880c6a03/pictures/field/2024_field.png" |
| alt="Starting Positions Image" |
| class="img-fluid" |
| /> |
| <div *ngFor="let i of [1, 2, 3, 4]"> |
| <label> |
| <input |
| type="radio" |
| name="radio-group" |
| [value]="i" |
| [(ngModel)]="selectedValue" |
| /> |
| {{ i }} |
| </label> |
| </div> |
| <div class="buttons"> |
| <!-- Creates a responsive stack of full-width, "block buttons". --> |
| <div class="d-grid gap-5"> |
| <button |
| class="btn btn-warning" |
| (click)="changeSectionTo('Review and Submit'); actionHelper.addNoShowAction({});" |
| > |
| No Show |
| </button> |
| <button |
| class="btn btn-primary" |
| [disabled]="!selectedValue" |
| (click)="changeSectionTo('Pickup'); actionHelper.addStartMatchAction({position: selectedValue});" |
| > |
| Start Match |
| </button> |
| </div> |
| </div> |
| </div> |
| <div *ngSwitchCase="'Pickup'" id="PickUp" class="container-fluid"> |
| <h6 class="text-muted"> |
| Last Action: {{ActionType[actionList[actionList.length - |
| 1].actionTakenType]}} |
| </h6> |
| <!-- |
| Decrease distance between buttons during auto to make space for auto balancing |
| selection and keep all buttons visible without scrolling on most devices. |
| --> |
| <div |
| [ngClass]="{'d-grid': true, 'gap-3': autoPhase === true, 'gap-5': autoPhase === false}" |
| > |
| <button class="btn btn-secondary" (click)="undoLastAction()">UNDO</button> |
| <button |
| class="btn btn-danger" |
| (click)="changeSectionTo('Dead'); actionHelper.addRobotDeathAction({robotDead: true});" |
| > |
| DEAD |
| </button> |
| <button |
| class="btn btn-warning" |
| (click)="changeSectionTo('Place'); actionHelper.addPickupNoteAction({auto: autoPhase});" |
| > |
| NOTE |
| </button> |
| <button |
| *ngIf="autoPhase && !mobilityCompleted" |
| class="btn btn-light" |
| (click)="actionHelper.addMobilityAction({mobility: true});" |
| > |
| Mobility |
| </button> |
| <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-primary" |
| (click)="autoPhase = false; actionHelper.addEndAutoPhaseAction({});" |
| > |
| Start Teleop |
| </button> |
| <button |
| *ngIf="!autoPhase" |
| class="btn btn-primary" |
| (click)="changeSectionTo('Endgame'); actionHelper.addEndTeleopPhaseAction({});" |
| > |
| Endgame |
| </button> |
| </div> |
| </div> |
| <div *ngSwitchCase="'Place'" id="Place" class="container-fluid"> |
| <h6 class="text-muted"> |
| Last Action: {{ActionType[actionList[actionList.length - |
| 1].actionTakenType]}} |
| </h6> |
| <!-- |
| Decrease distance between buttons during auto to make space for auto balancing |
| selection and keep all buttons visible without scrolling on most devices. |
| --> |
| <div |
| [ngClass]="{'d-grid': true, 'gap-4': autoPhase === true, 'gap-3': autoPhase === false}" |
| > |
| <button class="btn btn-secondary" (click)="undoLastAction()">UNDO</button> |
| <button |
| class="btn btn-danger" |
| (click)="changeSectionTo('Dead'); actionHelper.addRobotDeathAction({robotDead: true});" |
| > |
| DEAD |
| </button> |
| <div class="half-button-container"> |
| <button |
| class="btn btn-info half-button" |
| (click)="changeSectionTo('Pickup'); actionHelper.addPlaceNoteAction({auto: autoPhase, scoreType: ScoreType.kDROPPED});" |
| > |
| Dropped |
| </button> |
| <button |
| class="btn btn-info half-button" |
| (click)="changeSectionTo('Pickup'); actionHelper.addPlaceNoteAction({auto: autoPhase, scoreType: ScoreType.kOUT_OF_FIELD});" |
| > |
| Out Of Field |
| </button> |
| </div> |
| <div |
| *ngIf="!autoPhase" |
| class="d-grid gap-1" |
| style="padding: 0; margin: 0" |
| > |
| <div class="half-button-container"> |
| <button |
| class="btn btn-success half-button" |
| (click)="changeSectionTo('Pickup'); actionHelper.addPlaceNoteAction({auto: autoPhase, scoreType: ScoreType.kAMP});" |
| > |
| AMP |
| </button> |
| |
| <button |
| class="btn btn-warning half-button" |
| (click)="changeSectionTo('Pickup'); actionHelper.addPlaceNoteAction({auto: autoPhase, scoreType: ScoreType.kSHUTTLED});" |
| > |
| SHUTTLED |
| </button> |
| <button |
| class="btn btn-success half-button" |
| (click)="changeSectionTo('Pickup'); actionHelper.addPlaceNoteAction({auto: autoPhase, scoreType: ScoreType.kSPEAKER});" |
| > |
| SPEAKER |
| </button> |
| <button |
| class="btn btn-warning half-button" |
| (click)="changeSectionTo('Pickup'); actionHelper.addPlaceNoteAction({auto: autoPhase, scoreType: ScoreType.kSPEAKER_AMPLIFIED});" |
| > |
| SPEAKER AMPLIFIED |
| </button> |
| </div> |
| </div> |
| |
| <button |
| *ngIf="autoPhase" |
| class="btn btn-success" |
| (click)="changeSectionTo('Pickup'); actionHelper.addPlaceNoteAction({auto: autoPhase, scoreType: ScoreType.kAMP});" |
| > |
| AMP |
| </button> |
| <button |
| *ngIf="autoPhase" |
| class="btn btn-warning" |
| (click)="changeSectionTo('Pickup'); actionHelper.addPlaceNoteAction({auto: autoPhase, scoreType: ScoreType.kSPEAKER});" |
| > |
| SPEAKER |
| </button> |
| <button |
| *ngIf="autoPhase && !mobilityCompleted" |
| class="btn btn-light" |
| (click)="actionHelper.addMobilityAction({mobility: true});" |
| > |
| Mobility |
| </button> |
| <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 |
| class="btn btn-primary" |
| *ngIf="autoPhase" |
| (click)="autoPhase = false; actionHelper.addEndAutoPhaseAction({});" |
| > |
| Start Teleop |
| </button> |
| <button |
| *ngIf="!autoPhase" |
| class="btn btn-primary" |
| (click)="changeSectionTo('Endgame'); actionHelper.addEndTeleopPhaseAction({});" |
| > |
| Endgame |
| </button> |
| </div> |
| </div> |
| <div *ngSwitchCase="'Endgame'" id="Endgame" class="container-fluid"> |
| <h6 class="text-muted"> |
| Last Action: {{ActionType[actionList[actionList.length - |
| 1].actionTakenType]}} |
| </h6> |
| <div class="d-grid gap-2"> |
| <button class="btn btn-secondary" (click)="undoLastAction()">UNDO</button> |
| <button |
| class="btn btn-danger" |
| (click)="changeSectionTo('Dead'); actionHelper.addRobotDeathAction({robotDead: true});" |
| > |
| DEAD |
| </button> |
| <div class="button_row"> |
| <label> |
| <input |
| type="radio" |
| name="endgameaction" |
| [value]="StageType.kPARK" |
| [(ngModel)]="endGameAction" |
| /> |
| Park |
| </label> |
| <label> |
| <input |
| type="radio" |
| name="endgameaction" |
| [value]="StageType.kON_STAGE" |
| [(ngModel)]="endGameAction" |
| /> |
| On Stage |
| </label> |
| </div> |
| <div class="button_row"> |
| <label> |
| <input |
| type="radio" |
| name="endgameaction" |
| [value]="StageType.kHARMONY" |
| [(ngModel)]="endGameAction" |
| /> |
| Harmony |
| </label> |
| <label> |
| <input |
| type="radio" |
| name="endgameaction" |
| [value]="StageType.kMISSING" |
| [(ngModel)]="endGameAction" |
| /> |
| N/A |
| </label> |
| </div> |
| <label> |
| <input type="checkbox" name="trapnote" [(ngModel)]="noteIsTrapped" /> |
| Trap Note |
| </label> |
| <label> |
| <input |
| type="checkbox" |
| name="spotlight" |
| [(ngModel)]="endGameSpotlight" |
| /> |
| Spotlight |
| </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-primary" |
| (click)="changeSectionTo('Review and Submit'); addPenalties(); actionHelper.addEndMatchAction({stageType: endGameAction, trapNote: noteIsTrapped, spotlight: endGameSpotlight});" |
| > |
| End Match |
| </button> |
| </div> |
| </div> |
| <div *ngSwitchCase="'Dead'" id="Dead" class="container-fluid"> |
| <h2>Robot is dead</h2> |
| <div class="d-grid gap-3"> |
| <button class="btn btn-secondary" (click)="undoLastAction()">UNDO</button> |
| <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 |
| class="btn btn-success" |
| (click)="changeSectionTo('Pickup'); actionHelper.addRobotDeathAction({robotDead: false}); " |
| > |
| Revive |
| </button> |
| <button |
| class="btn btn-primary" |
| (click)="changeSectionTo('Review and Submit'); addPenalties(); actionHelper.addEndMatchAction({stageType: endGameAction, trapNote: noteIsTrapped, spotlight: endGameSpotlight});" |
| > |
| End Match |
| </button> |
| </div> |
| </div> |
| <div *ngSwitchCase="'Review and Submit'" id="Review" class="container-fluid"> |
| <div class="row"> |
| <ul id="review_data"> |
| <div *ngIf="compType!='Regular'">This is a {{this.compType}} match</div> |
| <li *ngFor="let action of actionList" style="display: flex"> |
| <div [ngSwitch]="action.actionTakenType" style="padding: 0px"> |
| <span *ngSwitchCase="ActionType.StartMatchAction"> |
| Started match at position {{(action.actionTaken | cast: |
| StartMatchActionT).position}} |
| </span> |
| <span *ngSwitchCase="ActionType.PickupNoteAction"> |
| Picked up Note |
| </span> |
| <span *ngSwitchCase="ActionType.PlaceNoteAction"> |
| Placed at {{stringifyScoreType((action.actionTaken | cast: |
| PlaceNoteActionT).scoreType)}} |
| </span> |
| <span *ngSwitchCase="ActionType.EndAutoPhaseAction"> |
| Ended auto phase |
| </span> |
| <span *ngSwitchCase="ActionType.EndMatchAction"> |
| Ended Match; stageType: {{stringifyStageType((action.actionTaken | |
| cast: EndMatchActionT).stageType)}}, trapNote: |
| {{(action.actionTaken | cast: EndMatchActionT).trapNote}}, |
| spotlight: {{(action.actionTaken | cast: |
| EndMatchActionT).spotlight}} |
| </span> |
| <span *ngSwitchCase="ActionType.RobotDeathAction"> |
| Robot dead: {{(action.actionTaken | cast: |
| RobotDeathActionT).robotDead}} |
| </span> |
| <span *ngSwitchCase="ActionType.MobilityAction"> |
| Mobility: {{(action.actionTaken | cast: |
| MobilityActionT).mobility}} |
| </span> |
| <span *ngSwitchCase="ActionType.NoShowAction">NoShow: true</span> |
| <span *ngSwitchDefault>{{action.actionTakenType}}</span> |
| <span *ngSwitchCase="ActionType.PenaltyAction"> |
| Penalties: {{(action.actionTaken | cast: |
| PenaltyActionT).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-info" (click)="changeSectionTo('QR Code');"> |
| Create QR Code |
| </button> |
| <button class="btn btn-warning" (click)="submit2024Actions();"> |
| Submit |
| </button> |
| </div> |
| </div> |
| <div *ngSwitchCase="'Success'" id="Success" class="container-fluid"> |
| <h2>Successfully submitted data.</h2> |
| <div class="d-grid gap-5" *ngIf="nextTeamNumber != ''"> |
| <button class="btn btn-primary" (click)="goToNextTeam();"> |
| SCOUT NEXT TEAM |
| </button> |
| </div> |
| </div> |
| <div *ngSwitchCase="'QR Code'" id="QR Code" class="container-fluid"> |
| <span>Density:</span> |
| <select |
| [(ngModel)]="qrCodeValuePieceSize" |
| (ngModelChange)="updateQrCodeValuePieceSize()" |
| type="number" |
| id="qr_code_piece_size" |
| > |
| <option |
| *ngFor="let pieceSize of QR_CODE_PIECE_SIZES" |
| [ngValue]="pieceSize" |
| > |
| {{pieceSize}} |
| </option> |
| </select> |
| <div class="qr-container"> |
| <qrcode |
| [qrdata]="qrCodeValuePieces[qrCodeValueIndex]" |
| [width]="1000" |
| [errorCorrectionLevel]="'M'" |
| [margin]="6" |
| class="qrcode" |
| ></qrcode> |
| </div> |
| <nav class="qrcode-nav"> |
| <ul |
| class="qrcode-buttons pagination pagination-lg justify-content-center" |
| > |
| <li class="page-item"> |
| <a |
| class="page-link" |
| href="#" |
| aria-label="Previous" |
| (click)="setQrCodeValueIndex(qrCodeValueIndex - 1)" |
| > |
| <span aria-hidden="true">«</span> |
| <span class="visually-hidden">Previous</span> |
| </a> |
| </li> |
| <li *ngFor="let _ of qrCodeValuePieces; index as i" class="page-item"> |
| <a |
| class="page-link" |
| href="#" |
| (click)="setQrCodeValueIndex(i)" |
| [class.active]="qrCodeValueIndex == i" |
| > |
| {{i + 1}} |
| </a> |
| </li> |
| <li class="page-item"> |
| <a |
| class="page-link" |
| href="#" |
| aria-label="Next" |
| (click)="setQrCodeValueIndex(qrCodeValueIndex + 1)" |
| > |
| <span aria-hidden="true">»</span> |
| <span class="visually-hidden">Next</span> |
| </a> |
| </li> |
| </ul> |
| </nav> |
| <button |
| class="btn btn-secondary" |
| (click)="changeSectionTo('Review and Submit')" |
| > |
| BACK |
| </button> |
| </div> |
| |
| <span class="progress_message" role="alert">{{ progressMessage }}</span> |
| <span class="error_message" role="alert">{{ errorMessage }}</span> |
| </ng-container> |