86 Tasks I Completed to Build an Evacuation Drill App

In this blog post, please find a lengthy list of tasks I performed over the past 8 months to complete my Senior Software Engineering Capstone Project. These tasks were reported at asynchronous weekly Standup "Discussions".

I do not recommend reading the entire list, but a light skim may be intriguing.

  1. Performed "elevation" tests on physical devices (iPhone and Android), gathered data, and set time to perform another round of tests.
  2. Maintained a pre-alpha dependency of our project (SurveyKit Flutter package).
  3. Implemented "DrillEvent" model
  4. Implemented "DrillEvent.example()" constructor with example data
  5. Switched source of Pre- and Post-DrillSurveys to DrillEvent.example()
  6. Implemented "Confirm Drill Details" page [fig. 1]
  7. Implemented "During Drill" page while pair-coding with Jasmine [fig. 2]
  8. Implemented Navigator with basic app flow
  9. Made choice with Jasmine to not use "bloc" for state management
  10. Met with Project Partners and provided update on current status of the app
  11. Requested and gained permission to set up shared Google credentials for the project in order to be ready to start spinning up the cloud databases
  12. Helped Dean setup development environment
  13. Performed test of elevation on iOS and Android, making initial confirmation of consistently lower elevation output on Android and consistently correct elevation output on iOS [fig. 3, courtesy of Dean]
  14. Based on excellent feedback from Jasmine, tested Strava on my dev Android device to confirm the elevation offset issue we are facing can be coded away. See the screenshot of the correct elevation at my house (from Strava, ~100 m) vs incorrect elevation at the beach (from our prototype, ~ -30 m)
  15. Ran into a wall when setting up the cloud with the group, and emailed our project partner requesting they meet with us to enter payment details for the cloud
  16. When we did not receive a response for several days, explored an alternative: Using Firebase as an in route to Google Firestore (the initial service we wanted to use, but with Firebase there is a free tier that does not require payment details to be input)
  17. Did the extensive development setup/integration for Firebase with the group
  18. Got an example of passing data using the Firebase Firestore working
  19. Implemented the communications from the app to the cloud
  20. Populated the "DrillEvent" object with data from the cloud
  21. Completed the "Distribute" and "Instruction" aspects of the Midpoint Project Archive
  22. Emailed the completed Midpoint Project Archive to the project partners
  23. Got a more illustrative demo of the cloud working in the app
  24. Met with the project partners to present progress and instructed primary project partner on how to add payment details to the Firebase.
  25. Implemented the DrillResults model, along with methods to parse SurveyKit SurveyResults objects into JSON
  26. Worked with Jasmine to get her dev environment back up and running after breaking changes.
  27. Implemented the LocationTracker class which streams location data to the local SQLite database during the drill and then calls the previously implemented "CreateGpx" class to, well, create a gpx file.
  28. Implemented an Asymmetric KeyGen and Asymmetric Block Cipher based on RSA, Fortuna, and AES using the pointy_castle dart package to encrypt files before cloud upload and decrypt after cloud download.
  29. Integrated the location tracking functionality into the BasicDrillPresenter to run while a participant is viewing the "DuringDrill" page. (**This implementation is fragile due to lack of persistence.)
  30. Created Cloud Storage directory for DrillResults in Firebase (will be sorted by DrillEvent.id subdirectories, then user.id sub-subdirectories).
  31. Implemented upload of encrypted results from participant app to Cloud Storage in Firebase. (**This implementation is fragile due to lack of negotiation with Cloud/server for unique user id.)
  32. Implemented unique user id negotiation on DrillConfirm participant action.
  33. Found the easiest way to bulk export DrillResults, which turned out to be using Google Cloud Functions to access our Cloud Storage, then calling the cloud function via https, using a message signature to validate the identity of researchers
  34. Ensured RSA message signing is interoperable between current Dart codebase & new JS Cloud Function codebase
  35. Initialized Cloud Functions for our Firebase project
  36. Wrote a Cloud Function which verifies a DrillEvent Firebase Document ID is signed by an authorized researcher, and if so collects all the (encrypted) results that participant have uploaded to Cloud Firestore from the mobile app, zips these result files, and returns the zipped archive as a download.
  37. Hooked the above Cloud Function into a development (not production) https endpoint
  38. Initialized the Flutter Researcher Console, now that we are sure we can access our Firebase data via https calls to our serverless backend (Cloud Functions)
  39. Created an initial page for the Researcher Console which accepts a DrillEvent Firebase Document ID and a downloads location on the local machine.
  40. Implemented a function in the Researcher Console which signs the input ID using the relevant hardcoded private key, obtains the zipped archive of encoded result files via an https request to the Cloud Function endpoint, unzips the archive, decrypts and parses the files contained in the archive, and saves the resultant csv table and gpx files to the indicated downloads location on the local machine.
  41. Collected about a dozen "trajectories" using both Strava and our Evac. App (on both iOS and Android devices) to compare/contrast our new toolchain to the one previously use by our Project Partners
  42. Downloaded and decrypted all results
  43. Installed a VS Code extension which allowed me to view the "trajectories" within the IDE, superseding Dean's task in issue #91 of generating .jpg files from all .gpx files.
  44. Compiled Android app to Emulator, resolving any errors which crop up
  45. Uploaded all .gpx "trajectory" results to Shared Google Drive
  46. Analyze the results of the "trajectories", making initial screenshots and graphs
  47. Determined that offsetting the Android elevation likely will be worthless due to significant noise in data
  48. Began documentation of recommended feature additions for future teams working with this project
  49. Registered for Expo (In-Person & virtual)
  50. Worked with Jasmine on reflow of app (see her post for primary things) (previously named "DrillTaskMenu" in sprint plan)
  51. Code Review Dean's work with package progress_indicator_button on invite_code_page.dart
  52. Analyzed the results of location data gathering to:
    • Generate 3 distinct conclusions:
      1. Need an “Acquiring GPS Signal” Feature, like Strava’s
      2. Android output noisier data than iPhone, regardless of app
      3. Strava queries an API for elevation data, not the device sensor
    • Generate slide deck based on results, visuals, and conclusions
  53. Presented results and conclusions to Project Partners with group
  54. Implemented new admin cloud endpoint which allows for the remote creation and upload of DrillEvents in Firestore, with unique (to system) 6 digit invite code generated and returned from endpoint.
  55. Completed "Wave swipe" animation to change screens at beginning of app flow
  56. Made a breakthrough on developing our Cloud Security:
    • We only need to `read` from Firestore for the DrillEvent details
    • We only need to `write` from Cloud Storage to upload results
    • If only one or the other is active on a given service, a malicious actor cannot use it as free storage space (this was my main concern)
    • Everything else is backend with admin permissions, so front facing security rules don't apply
  57. Implemented the above restrictions as rules, meaning that our cloud services are no longer at risk of unauthorized use (it would serve no purpose) and can therefore remain live at all times. All data is public, not an issue if someone does read. They would need our private API keys anyways.
  58. Had the opportunity to learn more about Cloud Security when I realized we actually do have a `write` call to Firestore. It's for a future feature (indicating to researchers that a given participant is ready for drill to begin)
  59. Implemented an exception to the Firestore rule for `participants` sub-collections to `DrillEvents` documents, allowing for specific `write`s to be performed
  60. Redefined overall data structure of the app to incorporate Tasks Page
  61. DrillResult is now DrillResults
    • has a list of TaskResults (see below)
  62. DrillEvent is now DrillDetails
    • has a list of DrillTasks
  63. DrillTasks model class is defined
    • has enumerated DrillTaskType
      • Survey
      • AllowLocationPermissions
      • WaitForStart
      • PerformDrill
      • Upload
      • Travel
    • has TaskDetails child
  64. TaskDetails model class extended for each DrillTaskType
  65. TaskResult model class extended for each DrillTaskType
    • has Function builder which adds TaskResult to DrillResults
  66. TaskDisplay Widget created for each DrillTaskType
  67. Incorporated Waves transition into app
  68. Completed Tasks Page
    • Has Oregon State brand asset icon (clipboard)
  69. TaskButton accomplished with ExpansionTileCard per Jasmine's research
    • has Function builders for TaskButton `onTap()`s for each DrillTaskType
  70. Jasmine's refreshed InviteCodePage incorporated into app
  71. Created presentation for NSF SCC focused research group meeting
  72. Presented app to NSF SCC focused research group
  73. Worked to finish transcript for project demo video
  74. Recorded, edited, uploaded projet demo video
  75. Added logo to InviteCodePage
  76. Code Reviewed Dean's recent Pull Requests
    • Incorporated his AboutDialog into refreshed InviteCodePage, under new logo
    • Incorporated his ProgressIndicatorButton into refreshed InviteCodePage
  77. Added Oregon State University logo (svg) to AboutDialog
  78. Added `onTap()` to InviteCodePage which removes focus from invite code entry box, thereby dismissing keyboard
  79. Changed keyboard back to numpad (on iOS doesn't have "done" dismiss keyboard button, so had switched to full keyboard to alleviate user frustration)
  80. Rerecorded and uploaded video with above changes to app walkthrough
  81. Completed Virtual Expo Website
  82. Nearly completed project poster, working on final visuals for bottom right picture
  83. Created TelemetryTest DrillDetails which has only tasks which test "location tracking" functionality (no surveys, etc.)
  84. Performed new Telemetry Comparison Test at beach: Torrey Pines State Nature Reserve
  85. Completed Project Poster with new visuals from new Telemetry Comparison Test
  86. Submitted Project Poster for printing