Skip to content

RISCfuture/icrashedmyplane.com

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Help, I Crashed My Plane!

Help, I Crashed My Plane! is a website that assists pilots in navigating 49 CFR § 830 (a.k.a. NTSB 830), the regulations governing reporting incidents and accidents to the NTSB. Using those laws as a basis, it asks a series of questions to determine if the incident qualifies as a serious incident or accident, and then gives the user the appropriate reporting instructions they need to follow.

This website is written in TypeScript using Vue.js. State management is done with Vuex and localization is done using i18n-vue (though American English is currently the only supported locale).

Vue CLI is the toolchain used to develop this website. Most operations are powered by vue-cli-service via Yarn. The package.json file has yarn aliases for all common development and deployment tasks.

Tasks

Installation

To run a copy of this website, simply check out this project into a directory, then run yarn install in that directory.

Running in development

yarn serve will compile the source with Webpack, and run a local development server at http://localhost:8080. The development web server supports hot-reloading.

Running tests

This website has both unit tests (written using Mocha/Chai) and end-to-end tests (run using Cypress). To run unit tests, run yarn test:unit. Run yarn test:e2e to launch the Cypress test runner and run end-to-end tests.

Generating documentation

HTML documentation for the code can be generated by running yarn docs:generate. Documentation will be in the docs directory.

Deployment

This website is hosted using GitHub Pages, and deployed automatically using GitHub Actions.

Architecture

This website works with two main object types, Surveys and Responses. A Survey contains the data necessary to build a series of questions that can be presented to the user. A Response encodes the user's answers to the Survey questions. Because which questions get asked depend on how previous questions were answered, both Surveys and Responses are stored as trees, though in different formats.

Terminology

Question refers to questions that are asked to the user, either single- or multiple-choice, and option refers to the available options for a question. Choice refers to which of the options the user selected.

An answer is an answer to a single question. A response is the collected answers that a user has given for a survey. A response is finished when all queries have been answered. A response is "effectively finished" when no possible future answers will change the outcome of the survey.

Incident level refers to whether an incident qualifies as non-serious (regular incident), a serious incident, or an accident. Leveling refers to marking a particular level as having been achieved (e.g., a user's answer qualifies the incident to be considered an accident). The final incident level is the highest of each answer's incident level.

Flag refers to information about the user which determines what queries to show. For example, queries regarding rotor blade damage will not be shown if the user was not flying a helicopter.

Surveys

A {@link Survey} is a tree organizing the queries that make up the survey. When the user is given the survey, the tree is traversed depth-first, and the user's answers determine which paths are followed or skipped.

The tree consists of the following node types:

Name Description Connects to
{@link Question} A question presented to the user. One or more Options
{@link Option} A possible option a user can choose for a Question. One Action
{@link Action} What to do after the user selects an Option. Either present a follow-up Question, or set the incident level (accident, incident, etc.). One Question, or null.

Surveys are stored in JavaScript files under src/data, and loaded at runtime into a dictionary. They are retrieved by their identifier (e.g., "incident" for the incident survey that is the raison d'etre of this website). The data/surveys.ts file contains an importable dictionary of all surveys, keyed by their identifier. The data/surveyOrder.ts file contains the order in which the surveys should be presented to the user.

Questions about the survey are answered using {@link SurveyTraverser}, which traverses the tree in a depth-first manner and uses a Visitor paradigm to pass events to the consumer.

Responses

A {@link Response} is a tree organizing the user's answers to each of the queries. It consists of the following nodes representing answers:

{@link QuestionNode} Contains a nodes array, where the selected options are represented by the presence of further nodes.

In addition, the following joining nodes are used:

{@link ActionNode} Joins QuestionNodes to their children.
{@link endNode} Marks the end of a path in the tree.

These nodes are all interrelated in the following ways:

QuestionNode contains a nodes array. For each option the user selected, an ActionNode is present in the array at that index, linking to the next QuestionNode for that path, or EndNode if that is the end of that path. For each option the user did not select, the array contains undefined.

Using ActionNode allows us to differentiate between the situation where the user did not choose an option (undefined) and where the user did choose an option but has not yet answered any follow-up questions resulting from that option (ActionNode linked to an EndNode).

Response trees are accessed using answer paths, which are arrays of numbers. Each element of the array is an index in a QuestionNode's nodes array to follow. Answer paths must terminate in an end node; incomplete paths are not allowed.

The {@link ResponseTraverser} class traverses a Survey and Response tree simultaneously. It is written nearly identically to the SurveyTraverser class, except the visitor callbacks yield corresponding nodes in both trees simultaneously.

Vuex Store

User state management is done with Vuex. The root Vuex module contains a dictionary of Responses for each Survey the user has completed, keyed by the survey identifier. As the user answers questions, the answers are added to the appropriate Response tree in Vuex.

Front End

The root Vue is the {@link App} view, which contains a single element, the {@link Container}. The App view creates the #app element which positions the content in the center of the page using a flexbox. The Container view handles rendering subviews and animating between them.

Most layout is done using flexboxes. The main view is fixed in horizontal extent above the mobile break, and allowed to flow in vertical extent with a minimum height.

Both light and dark themes are supported based on OS settings.

Styling is written using SCSS. The src/assets/styles directory contains global CSS (global.css) as well as a number of library functions and mixins used throughout the app. View-specific CSS is placed in the <style> tags within Vue files.

The font "Quicksand" is used throughout the application. It is a variable font, meaning that its weight (among other properties) can be varied fluidly. The weights used in this application are defined in _fonts.scss. The font is loaded in font-faces.scss.

Animations are used extensively throughout the app, powered by Vue transitions. These animations are defined in transitions.scss, which also contains a number of mixins designed to make writing animations less tedious.

Responsive behavior, including the mobile break and scaling of font and margin sizes, is done in _responsive.scss.

Testing

Unit tests are powered by Mocha using Chai's expect syntax. A fixtures.ts file contains example survey responses that can be used for testing.

Cypress tests are written in TypeScript. To prevent Mocha/Chai's globals from interfering with Cypress's globals, a custom tsconfig.json and cypress.d.ts have been placed in the test/e2e directory to isolate the Cypress namespace.

test/e2e/plugins/index.js has been modified to add a Webpack preprocessor that makes module path resolution work the same in both the application and Cypress environments. This way, application modules can be used in Cypress tests. This was done because ResponseTraverser is used by Cypress to run test flows from fixture responses (genius!).

About

A website to help people navigate NTSB 830

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published