diff --git a/subtrees/the-blue-alliance-react/.gitignore b/subtrees/the-blue-alliance-react/.gitignore
index 2e0bf4de5..4c62435da 100644
--- a/subtrees/the-blue-alliance-react/.gitignore
+++ b/subtrees/the-blue-alliance-react/.gitignore
@@ -4,4 +4,9 @@ node_modules
.nvm
ios/
-ios.zip
+android/
+react-native.zip
+gcp-service-key.json
+*-tba-dev-*.json
+*-firebase-*.json
+ops/deploy_keys.tar
diff --git a/subtrees/the-blue-alliance-react/.travis.yml b/subtrees/the-blue-alliance-react/.travis.yml
new file mode 100644
index 000000000..0d383c814
--- /dev/null
+++ b/subtrees/the-blue-alliance-react/.travis.yml
@@ -0,0 +1,34 @@
+language: node_js
+
+branches:
+ only:
+ - master
+
+before_install:
+ - nvm install 9
+
+install:
+ - travis_retry npm install
+ - travis_retry npm install -g react-native-cli
+
+before_deploy:
+ - openssl aes-256-cbc -K $encrypted_e4ef44d57242_key -iv $encrypted_e4ef44d57242_iv -in ops/deploy_keys.tar.enc -out ops/deploy_keys.tar -d
+ - ./ops/manage_deploy_keys.sh -x
+
+stages:
+ - test
+ - name: deploy
+ if: (type = push) AND (branch = master)
+
+jobs:
+ include:
+ - script: npm test
+ - stage: deploy
+ script: skip
+ deploy:
+ skip_cleanup: true
+ provider: script
+ script: ./ops/travis-deploy.sh
+ on:
+ branch: master
+
diff --git a/subtrees/the-blue-alliance-react/README.md b/subtrees/the-blue-alliance-react/README.md
index 22058ef2d..b7111e19e 100644
--- a/subtrees/the-blue-alliance-react/README.md
+++ b/subtrees/the-blue-alliance-react/README.md
@@ -1,4 +1,4 @@
-The Blue Alliance - Rect Native
+The Blue Alliance - React Native
===
React Native code used in The Blue Alliance's iOS app
@@ -29,23 +29,25 @@ You can test the React Native code locally with [The Blue Alliance for iOS](http
* To view RN logs: `react-native log-ios`
* Debugging is easier if you install [react-devtools](https://github.com/facebook/react-devtools/tree/master/packages/react-devtools)
-
-Building
+Building Locally
===
-For compiling the React Native bundle to be used offline. The iOS app expects the hosted files to be zipped in a file called `ios.zip`
+For compiling the React Native bundle to be used offline. The iOS app expects the hosted files to be zipped in a file called `react-native.zip`
```
-$ mkdir ios
$ react-native bundle --platform ios --dev false --assets-dest ios --entry-file index.ios.js --bundle-output ios/main.jsbundle --reset-cache
-$ zip -r ios.zip ios/
+$ zip -r react-native.zip ios/
```
+Building and Deploying with Travis
+===
+For building and deploying with Travis, follow the setup guide available [HERE](travis-setup.md).
+
Contributing
============
Want to add features, fix bugs, or just poke around the code? No problem!
-Project Communication
+Project Communication
---
- Keep up to date with the [mailing list](https://groups.google.com/forum/#!forum/thebluealliance-developers).
- Chat with us on our [Slack team](https://the-blue-alliance.slack.com/). (Request an invite in the mailing list.)
diff --git a/subtrees/the-blue-alliance-react/app/views/EventInsights2019.js b/subtrees/the-blue-alliance-react/app/views/EventInsights2019.js
new file mode 100644
index 000000000..f3222c8c9
--- /dev/null
+++ b/subtrees/the-blue-alliance-react/app/views/EventInsights2019.js
@@ -0,0 +1,111 @@
+'use strict';
+
+import React from 'react';
+import {
+ Text,
+ View
+} from 'react-native';
+import TableSectionHeader from '../componets/TableSectionHeader';
+import InsightRow from '../componets/InsightRow';
+import { round } from '../helpers/number';
+import {
+ scoreFor,
+ percentageFor,
+ bonusStat,
+ highScoreString,
+} from '../helpers/insights';
+
+export default class EventInsights2019 extends React.Component {
+ render() {
+ return (
+
+ {/* Match Stats */}
+ Match Stats
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Match Stats */}
+ Bonus Stats (# successful / # opportunities)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/subtrees/the-blue-alliance-react/app/views/MatchBreakdown2019.js b/subtrees/the-blue-alliance-react/app/views/MatchBreakdown2019.js
new file mode 100644
index 000000000..14715ad01
--- /dev/null
+++ b/subtrees/the-blue-alliance-react/app/views/MatchBreakdown2019.js
@@ -0,0 +1,169 @@
+import React from 'react';
+import ReactNative from 'react-native';
+import {
+ Text,
+ View
+} from 'react-native';
+import BreakdownRow from '../componets/BreakdownRow';
+import breakdown from '../styles/breakdown';
+import images from '../config/images';
+
+// Override our Image and Text to have specific sizes
+const Image = ({ style, ...props }) => ;
+
+export default class MatchBreakdown2019 extends React.Component {
+
+ checkImage() {
+ return (
+
+ );
+ }
+
+ xImage() {
+ return (
+
+ );
+ }
+
+ getSandstormBonusFor(breakdown, robotNumber) {
+ if (breakdown["habLineRobot" + robotNumber] == "CrossedHabLineInSandstorm") {
+ let result = breakdown["preMatchLevelRobot" + robotNumber]
+ if (result.includes("HabLevel")) {
+ return `Level ${result.substr(-1)}`
+ }
+ }
+ return "--"
+ }
+
+ getHABClimbFor(breakdown, robotNumber) {
+ let result = breakdown["endgameRobot" + robotNumber]
+ if (result.includes("HabLevel")) {
+ return `Level ${result.substr(-1)}`
+ }
+ return "--"
+ }
+
+ getCargoShipDataFor(breakdown) {
+ var panelCount = 0
+ var cargoCount = 0
+
+ for (let i = 1; i <= 8; i++) {
+ if (breakdown["bay" + i].includes("Panel")) {
+ panelCount++
+ }
+ if (breakdown["bay" + i].includes("Cargo")) {
+ panelCount++
+ }
+ }
+ return `${panelCount} / ${cargoCount}`
+ }
+
+ getRocketShipDataFor(breakdown, rocketLocation) {
+ var locations = [
+ "topLeftRocket",
+ "topRightRocket",
+ "midLeftRocket",
+ "midRightRocket",
+ "lowLeftRocket",
+ "lowRightRocket"
+ ]
+ var panelCount = 0
+ var cargoCount = 0
+ locations.forEach(location => {
+ if (breakdown[location + rocketLocation].includes("Panel")) {
+ panelCount++
+ }
+ if (breakdown[location + rocketLocation].includes("Cargo")) {
+ cargoCount++
+ }
+ });
+ return `${panelCount} / ${cargoCount}`
+ }
+
+
+ render() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {this.props.compLevel == "qm" ? : null}
+
+
+ );
+ }
+}
diff --git a/subtrees/the-blue-alliance-react/index.ios.js b/subtrees/the-blue-alliance-react/index.ios.js
index 365c01427..e7ffa4505 100755
--- a/subtrees/the-blue-alliance-react/index.ios.js
+++ b/subtrees/the-blue-alliance-react/index.ios.js
@@ -5,14 +5,18 @@ import MatchBreakdown2015 from './app/views/MatchBreakdown2015';
import MatchBreakdown2016 from './app/views/MatchBreakdown2016';
import MatchBreakdown2017 from './app/views/MatchBreakdown2017';
import MatchBreakdown2018 from './app/views/MatchBreakdown2018';
+import MatchBreakdown2019 from './app/views/MatchBreakdown2019';
import EventInsights2016 from './app/views/EventInsights2016';
import EventInsights2017 from './app/views/EventInsights2017';
import EventInsights2018 from './app/views/EventInsights2018';
+import EventInsights2019 from './app/views/EventInsights2019';
AppRegistry.registerComponent('MatchBreakdown2015', () => MatchBreakdown2015);
AppRegistry.registerComponent('MatchBreakdown2016', () => MatchBreakdown2016);
AppRegistry.registerComponent('MatchBreakdown2017', () => MatchBreakdown2017);
AppRegistry.registerComponent('MatchBreakdown2018', () => MatchBreakdown2018);
+AppRegistry.registerComponent('MatchBreakdown2019', () => MatchBreakdown2019);
AppRegistry.registerComponent('EventInsights2016', () => EventInsights2016);
AppRegistry.registerComponent('EventInsights2017', () => EventInsights2017);
AppRegistry.registerComponent('EventInsights2018', () => EventInsights2018);
+AppRegistry.registerComponent('EventInsights2019', () => EventInsights2019);
diff --git a/subtrees/the-blue-alliance-react/ios/.gitkeep b/subtrees/the-blue-alliance-react/ios/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/subtrees/the-blue-alliance-react/ops/deploy_keys.tar.enc b/subtrees/the-blue-alliance-react/ops/deploy_keys.tar.enc
new file mode 100644
index 000000000..746ff3966
Binary files /dev/null and b/subtrees/the-blue-alliance-react/ops/deploy_keys.tar.enc differ
diff --git a/subtrees/the-blue-alliance-react/ops/manage_deploy_keys.sh b/subtrees/the-blue-alliance-react/ops/manage_deploy_keys.sh
new file mode 100755
index 000000000..905814a1b
--- /dev/null
+++ b/subtrees/the-blue-alliance-react/ops/manage_deploy_keys.sh
@@ -0,0 +1,22 @@
+#! /bin/bash
+
+# A file to build a tarball of key files that get encrypted for travis
+# Any file in here should MOST DEFINITELY be in .gitignore
+# Run this script from the root of the repo. Use -c to build the archive, -x to extract
+
+while getopts "cx" o; do
+ case "${o}" in
+ c)
+ echo "Creating key archive..."
+ tar cvf ops/deploy_keys.tar ops/tbatv-prod-hrd-firebase-adminsdk.json
+ ;;
+ x)
+ echo "Extracting key archive..."
+ tar xvf ops/deploy_keys.tar
+ ;;
+ *)
+ exit -1
+ ;;
+ esac
+done
+
diff --git a/subtrees/the-blue-alliance-react/ops/travis-deploy.sh b/subtrees/the-blue-alliance-react/ops/travis-deploy.sh
new file mode 100755
index 000000000..78547ff4d
--- /dev/null
+++ b/subtrees/the-blue-alliance-react/ops/travis-deploy.sh
@@ -0,0 +1,33 @@
+#! /bin/bash
+set -eE
+
+echo "Building react native bundle..."
+react-native bundle --platform ios --dev false --assets-dest ios --entry-file index.ios.js --bundle-output ios/main.jsbundle
+zip -r react-native.zip ios/
+
+BASE='https://dl.google.com/dl/cloudsdk/channels/rapid/'
+NAME='google-cloud-sdk'
+EXT='.tar.gz'
+INSTALL=$HOME
+BOOTSTRAP="$INSTALL/$NAME/bin/bootstrapping/install.py"
+GCLOUD="$INSTALL/$NAME/bin/gcloud"
+
+with_python27() {
+ bash -c "source $HOME/virtualenv/python2.7/bin/activate; $1"
+}
+
+echo "Downloading Google Cloud SDK ..."
+curl -L "${BASE}${NAME}${EXT}" | gzip -d | tar -x -C ${INSTALL}
+
+echo "Bootstrapping Google Cloud SDK ..."
+with_python27 "$BOOTSTRAP --usage-reporting=false --command-completion=false --path-update=false"
+
+PATH=$PATH:$INSTALL/$NAME/bin/
+
+echo "Configuring service account auth..."
+gcloud -q auth activate-service-account --key-file ops/tbatv-prod-hrd-firebase-adminsdk.json
+
+firebase_bucket="gs://$google_cloud_project.appspot.com"
+gsutil cp react-native.zip $firebase_bucket/react-native/react-native.zip
+
+
diff --git a/subtrees/the-blue-alliance-react/travis-setup.md b/subtrees/the-blue-alliance-react/travis-setup.md
new file mode 100644
index 000000000..ede2c2129
--- /dev/null
+++ b/subtrees/the-blue-alliance-react/travis-setup.md
@@ -0,0 +1,105 @@
+# Building and Deploying with Travis
+
+### Setup Travis web
+ 1) To get started with Travis, follow the first 3 steps in the following tutorial:
+ - https://docs.travis-ci.com/user/tutorial/#to-get-started-with-travis-ci
+ - For step 3, make sure you include activating your fork of this repository
+
+### Create Firebase account
+ 1) Navigate to https://console.firebase.google.com
+ 2) Sign in/make an account
+ 3) Create a new project:
+ - For project name, use `{your username}-tba-dev`
+ - Leave the other settings to the defaults, unless you know what you're doing
+
+ ![](https://i.imgur.com/tk4kWtn.png)
+
+ 4) On the left, navigate to Develop -> Storage
+ - After clicking through a few confirmations, you should be on a screen like this:
+
+ ![](https://i.imgur.com/tpFcxrU.png)
+
+5) Copy your storage URL for later use:
+ - Copy the storage URL, which is `gs://dracco1993-tba-dev-17792.appspot.com` in this example, to some place you'll remember; we'll need this URL in a later step.
+
+### Create/Download Firebase keys
+ 1) On the top left of Firebase, click the gear icon, then go to Project Settings
+ 2) From here, go to the Service Accounts tab
+ 3) Click "Generate new private key", then confirm by clicking "Generate key"
+ - Generating a key in this manner will download a new `.json` file, containing all the information required to access this Firebase project via an API
+ - As the warning in Firebase says, "Keep it confidential and **never store it in a public repository**"
+
+### Encrypt Firebase keys with Travis CLI
+ 1) Setup the Travis CLI:
+ - https://github.com/travis-ci/travis.rb#installation
+ 2) Login to the Travis CLI
+ - First, make sure that you're inside this repository's directory in terminal before running commands. Being inside of the repository's directory allows Travis to automatically figure out the information necessary to link the following commands to your project in Travis, by looking at the `.git` metadata folder locally.
+
+ - Next, log in to Travis via the command line with the following command:
+ ```bash
+ $ travis login
+ ```
+ - As part of this command, Travis will ask you for you GitHub credentials. Travis does not store these. Rather, it uses them to generate an API token, verifies that you are who you say you are, then deletes the token.
+ - If you're weary of using your username and password, or want to learn more about what this command does, check out the following documentation for more details and other ways you can authenticate against GitHub:
+ - https://github.com/travis-ci/travis.rb#login
+
+ 3) Encrypt Firebase keys
+ - At this point, we need to encrypt the `.json` file that we downloaded from Firebase previously. Travis has a very nice way to do this, that allows us to upload the encrypted file inside our repository, but for only Travis to be able to decrypt it when it's actually running a build.
+ ```bash
+ $ travis encrypt-file PATH_TO_DOWNLOADED_FILE.json gcp-service-key.json.enc
+ ```
+ - This command encrypts the `.json` file from Firebase, and sets two environment variables in your Travis project
+ - Note: the input path will be to wherever you put the Firebase key file, but to keep things easier, the output path will be the encoded `.json.enc` file already in the repository
+ - The full documentation for this command is available here:
+ - https://github.com/travis-ci/travis.rb#encrypt-file
+ - Usages and examples can be found here:
+ - https://docs.travis-ci.com/user/encrypting-files/
+
+### Update Travis environment variables
+ 1) We need to update the environment variables that Travis uses to decrypt the `.json.enc` we just created
+ 2) First, navigate to the setting page for your repository by clicking More Options -> Settings in the top right hand corner:
+
+ ![](https://i.imgur.com/MGzMaT7.png)
+ 3) In the Environment Variables section, you should see two variables already defined for you, from when you encrypted the Firebase file with Travis CLI:
+
+ ![](https://i.imgur.com/A04Bua9.png)
+ 4) The first two variables we'll add are going to reference the two variables mentioned previously. The names will be static, as mentioned below, but the values will be the names of the generated keys, prefaced with a `$`:
+ - First, one to reference the key:
+ - Name: `encrypted_key_name`
+ - Value: `${name_of_encrypted_key_var}`
+ - Example: `$encrypted_cb3726d3b29b_key`
+ - Second, one to reference the iv:
+ - Name: `encrypted_iv_name`
+ - Value: `${name_of_encrypted_iv_var}`
+ - Example: `$encrypted_cb3726d3b29b_iv`
+ - The last variable we'll add is the reference to the Firebase storage we made earlier:
+ - Name: `firebase_bucket`
+ - Value: `gs://{your username}-tba-dev.appspot.com`
+ - Example: `gs://dracco1993-tba-dev-17792.appspot.com`
+ 5) Your final environment variable configuration should look something like this:
+
+ ![](https://i.imgur.com/ZquQttX.png)
+
+### Commit changes
+ 1) After following the previous steps, you should have one file that you've updated and need to commit to the repository:
+ - `gcp-service-key.json.enc`
+
+ NOTE: **make sure you DO NOT commit the unencrypted `.json` file**
+ 2) `git push` your changes
+
+### Confirmation everything worked
+ 1) Check Travis.
+ - After pushing, on the left-hand side you should see a build running for your repository
+ - Click the build to view more information:
+ - Scroll down to the bottom of the logs
+ - On the second to last line, you should see something like this:
+ ```bash
+ $ gsutil cp react-native.zip $firebase_bucket/react-native/react-native.zip
+ Copying file://react-native.zip [Content-Type=application/zip]...
+ / [1 files][173.6 KiB/173.6 KiB]
+ Operation completed over 1 objects/173.6 KiB.
+ ```
+ - If you see this, everything is working and you can continue on to the next step
+ 2) Check Firebase.
+ - Navigate to/refresh your Firebase storage page
+ - Inside the `react-native/` folder, you should see your final build: `react-native.zip`