Add climbing level to database

I spent a lot of time trying to make this use enums for the entire
data path. Unfortunately, I ran into a few issues. Firstly, I couldn't
figure out how make our Go SQL code happy with postgresql enums. I
kept getting errors about `unknown oid`. Secondly, I couldn't figure
out how to de-duplicate the enum between `submit_data_scouting.fbs`
and `request_data_scouting_response.fbs`. The generated Go code
doesn't import the dependency properly.

All this turned into an enum at the flatbuffer and TypeScript level,
but just an integer at the Go/postgres level.

A future patch can deal with this. Perhaps it'd be better to ignore
this altogether and just switch to a library like Gorm.

Signed-off-by: Philipp Schrader <philipp.schrader@gmail.com>
Change-Id: Id6cbb5502fd77f3107514b8d7cb9df2923a9d5f9
diff --git a/scouting/www/entry/entry.component.ts b/scouting/www/entry/entry.component.ts
index d067c3e..357d6b7 100644
--- a/scouting/www/entry/entry.component.ts
+++ b/scouting/www/entry/entry.component.ts
@@ -2,13 +2,11 @@
 import {FormsModule} from '@angular/forms';
 import {Builder, ByteBuffer} from 'flatbuffers';
 import {ErrorResponse} from 'org_frc971/scouting/webserver/requests/messages/error_response_generated';
-import {SubmitDataScouting} from 'org_frc971/scouting/webserver/requests/messages/submit_data_scouting_generated';
+import {ClimbLevel, SubmitDataScouting} from 'org_frc971/scouting/webserver/requests/messages/submit_data_scouting_generated';
 import {SubmitDataScoutingResponse} from 'org_frc971/scouting/webserver/requests/messages/submit_data_scouting_response_generated';
 
 type Section = 'Team Selection'|'Auto'|'TeleOp'|'Climb'|'Other'|
     'Review and Submit'|'Success';
-type Level = 'NoAttempt'|'Failed'|'FailedWithPlentyOfTime'|'Low'|'Medium'|
-    'High'|'Transversal';
 
 @Component({
   selector: 'app-entry',
@@ -16,6 +14,10 @@
   styleUrls: ['../common.css', './entry.component.css']
 })
 export class EntryComponent {
+  // Re-export the type here so that we can use it in the `[value]` attribute
+  // of radio buttons.
+  readonly ClimbLevel = ClimbLevel;
+
   section: Section = 'Team Selection';
   @Output() switchTabsEvent = new EventEmitter<string>();
   @Input() matchNumber: number = 1;
@@ -28,7 +30,7 @@
   teleShotsMissed: number = 0;
   defensePlayedOnScore: number = 0;
   defensePlayedScore: number = 0;
-  level: Level = 'NoAttempt';
+  level: ClimbLevel = ClimbLevel.NoAttempt;
   ball1: boolean = false;
   ball2: boolean = false;
   ball3: boolean = false;
@@ -56,6 +58,7 @@
     } else if (this.section === 'Other') {
       this.section = 'Review and Submit';
     } else if (this.section === 'Review and Submit') {
+
       this.submitDataScouting();
       return;
     } else if (this.section === 'Success') {
@@ -109,10 +112,8 @@
     SubmitDataScouting.addAutoBall4(builder, this.ball4);
     SubmitDataScouting.addAutoBall5(builder, this.ball5);
     SubmitDataScouting.addStartingQuadrant(builder, this.quadrant);
-
     // TODO(phil): Add support for defensePlayedOnScore.
-    // TODO(phil): Fix the Climbing score.
-    SubmitDataScouting.addClimbing(builder, 1);
+    SubmitDataScouting.addClimbLevel(builder, this.level);
     builder.finish(SubmitDataScouting.endSubmitDataScouting(builder));
 
     const buffer = builder.asUint8Array();
diff --git a/scouting/www/entry/entry.module.ts b/scouting/www/entry/entry.module.ts
index b4d81c0..45a8a62 100644
--- a/scouting/www/entry/entry.module.ts
+++ b/scouting/www/entry/entry.module.ts
@@ -1,12 +1,21 @@
-import {NgModule} from '@angular/core';
+import {NgModule, Pipe, PipeTransform} from '@angular/core';
 import {CommonModule} from '@angular/common';
 import {FormsModule} from '@angular/forms';
 
 import {CounterButtonModule} from '../counter_button/counter_button.module';
 import {EntryComponent} from './entry.component';
 
+import {ClimbLevel} from 'org_frc971/scouting/webserver/requests/messages/submit_data_scouting_generated';
+
+@Pipe({name: 'levelToString'})
+export class LevelToStringPipe implements PipeTransform {
+  transform(level: ClimbLevel): string {
+    return ClimbLevel[level];
+  }
+}
+
 @NgModule({
-  declarations: [EntryComponent],
+  declarations: [EntryComponent, LevelToStringPipe],
   exports: [EntryComponent],
   imports: [CommonModule, FormsModule, CounterButtonModule],
 })
diff --git a/scouting/www/entry/entry.ng.html b/scouting/www/entry/entry.ng.html
index 5849f3b..ead9f83 100644
--- a/scouting/www/entry/entry.ng.html
+++ b/scouting/www/entry/entry.ng.html
@@ -69,19 +69,19 @@
 
     <div *ngSwitchCase="'Climb'" id="climb" class="container-fluid">
         <form>
-            <input [(ngModel)]="level" type="radio" name="level" id="no_attempt" value="NoAttempt">
+            <input [(ngModel)]="level" type="radio" name="level" id="no_attempt" [value]="ClimbLevel.NoAttempt">
             <label for="no_attempt">No climbing attempt</label><br>
-            <input [(ngModel)]="level" type="radio" name="level" id="low" value="Low">
+            <input [(ngModel)]="level" type="radio" name="level" id="low" [value]="ClimbLevel.Low">
             <label for="low">Low</label><br>
-            <input [(ngModel)]="level" type="radio" name="level" id="medium" value="Medium">
+            <input [(ngModel)]="level" type="radio" name="level" id="medium" [value]="ClimbLevel.Medium">
             <label for="medium">Medium</label><br>
-            <input [(ngModel)]="level" type="radio" name="level" id="high" value="High">
+            <input [(ngModel)]="level" type="radio" name="level" id="high" [value]="ClimbLevel.High">
             <label for="high">High</label><br>
-            <input [(ngModel)]="level" type="radio" name="level" id="transversal" value="Transversal">
+            <input [(ngModel)]="level" type="radio" name="level" id="transversal" [value]="ClimbLevel.Transversal">
             <label for="transversal">Transversal</label><br>
-            <input [(ngModel)]="level" type="radio" name="level" id="failed" value="Failed">
+            <input [(ngModel)]="level" type="radio" name="level" id="failed" [value]="ClimbLevel.Failed">
             <label for="failed">Failed</label><br>
-            <input [(ngModel)]="level" type="radio" name="level" id="failed_with_plenty_of_time" value="FailedWithPlentyOfTime">
+            <input [(ngModel)]="level" type="radio" name="level" id="failed_with_plenty_of_time" [value]="ClimbLevel.FailedWithPlentyOfTime">
             <label for="failed_with_plenty_of_time">Failed (attempted with more than 10 seconds left)</label><br>
         </form>
         <div class="row">
@@ -177,7 +177,7 @@
 
         <h4>Climb</h4>
         <ul>
-            <li>Level: {{level}}</li>
+            <li>Level: {{level | levelToString}}</li>
         </ul>
 
         <h4>Other</h4>