Skip to content
Snippets Groups Projects
Commit ec8c0c3e authored by Brady James Garvin's avatar Brady James Garvin
Browse files

Initial commit.

parents
No related branches found
No related tags found
No related merge requests found
.eslintrc 0 → 100755
{
"env": {
"es6": true,
"browser": true,
"jquery": true,
},
"rules": {
"no-await-in-loop": "warn",
"no-compare-neg-zero": "warn",
"no-cond-assign": "warn",
"no-console": "off",
"no-constant-condition": "warn",
"no-control-regex": "warn",
"no-debugger": "warn",
"no-dupe-args": "warn",
"no-dupe-keys": "warn",
"no-duplicate-case": "warn",
"no-empty": "warn",
"no-empty-character-class": "warn",
"no-ex-assign": "warn",
"no-extra-boolean-cast": "warn",
"no-extra-parens": ["warn", "all", {
"nestedBinaryExpressions": false,
}],
"no-extra-semi": "warn",
"no-func-assign": "warn",
"no-inner-declarations": "warn",
"no-invalid-regexp": "warn",
"no-irregular-whitespace": "warn",
"no-obj-calls": "warn",
"no-prototype-builtins": "warn",
"no-regex-spaces": "warn",
"no-sparse-arrays": "warn",
"no-template-curly-in-string": "warn",
"no-unexpected-multiline": "warn",
"no-unreachable": "warn",
"no-unsafe-finally": "warn",
"no-unsafe-negation": "warn",
"use-isnan": "warn",
"valid-jsdoc": "warn",
"valid-typeof": "warn",
"accessor-pairs": "warn",
"array-callback-return": "warn",
"block-scoped-var": "warn",
"class-methods-use-this": "warn",
"complexity": "off",
"consistent-return": "warn",
"curly": "warn",
"default-case": "off",
"dot-location": "warn",
"dot-notation": "warn",
"eqeqeq": "warn",
"guard-for-in": "off", // see no-restricted-syntax
"no-alert": "warn",
"no-caller": "warn",
"no-case-declarations": "warn",
"no-div-regex": "warn",
"no-else-return": "warn",
"no-empty-function": "warn",
"no-empty-pattern": "warn",
"no-eq-null": "warn",
"no-eval": "warn",
"no-extend-native": "off",
"no-extra-bind": "warn",
"no-extra-label": "warn",
"no-fallthrough": "warn",
"no-floating-decimal": "warn",
"no-global-assign": "warn",
"no-implicit-coercion": "warn",
"no-implicit-globals": "off",
"no-implied-eval": "warn",
"no-invalid-this": "off",
"no-iterator": "warn",
"no-labels": "off",
"no-lone-blocks": "off",
"no-loop-func": "warn",
"no-magic-numbers": ["warn", {
"ignore": [-1, 0, 0.001, 0.5, 1, 2, 10, 100, 180, 360, 1000],
"detectObjects": true,
}],
"no-multi-spaces": "warn",
"no-multi-str": "warn",
"no-new": "warn",
"no-new-func": "warn",
"no-new-wrappers": "warn",
"no-octal": "warn",
"no-octal-escape": "warn",
"no-param-reassign": "warn",
"no-proto": "warn",
"no-redeclare": "warn",
"no-restricted-properties": "warn",
"no-return-assign": "warn",
"no-return-await": "warn",
"no-script-url": "warn",
"no-self-assign": "warn",
"no-self-compare": "warn",
"no-sequences": "warn",
"no-throw-literal": "warn",
"no-unmodified-loop-condition": "warn",
"no-unused-expressions": "warn",
"no-unused-labels": "warn",
"no-useless-call": "warn",
"no-useless-concat": "warn",
"no-useless-escape": "warn",
"no-useless-return": "warn",
"no-void": "warn",
"no-warning-comments": "warn",
"no-with": "warn",
"prefer-promise-reject-errors": "warn",
"radix": "warn",
"require-await": "warn",
"vars-on-top": "off",
"wrap-iife": "warn",
"yoda": "warn",
"strict": ["warn", "never"],
"init-declarations": "warn",
"no-catch-shadow": "warn",
"no-delete-var": "warn",
"no-label-var": "warn",
"no-restricted-globals": "warn",
"no-shadow": "warn",
"no-shadow-restricted-names": "warn",
"no-undef": "warn",
"no-undef-init": "off",
"no-undefined": "off",
"no-unused-vars": ["warn", {
"varsIgnorePattern": "_+",
}],
"no-use-before-define": "warn",
"array-bracket-spacing": "warn",
"block-spacing": "warn",
"brace-style": "warn",
"camelcase": "warn",
"capitalized-comments": "off",
"comma-dangle": ["warn", "always-multiline"],
"comma-spacing": "warn",
"comma-style": "warn",
"computed-property-spacing": "warn",
"consistent-this": "warn",
"eol-last": "warn",
"func-call-spacing": "warn",
"func-name-matching": "warn",
"func-names": ["warn", "as-needed"],
"func-style": "off",
"id-blacklist": ["warn", "temp"],
"id-length": "off",
"id-match": "off",
"indent": ["warn", 2],
"jsx-quotes": "warn",
"key-spacing": "warn",
"keyword-spacing": "warn",
"line-comment-position": "off",
"linebreak-style": "warn",
"lines-around-comment": "off",
"lines-around-directive": "warn",
"max-depth": "off",
"max-len": "off",
"max-lines": "off",
"max-nested-callbacks": "off",
"max-params": "off",
"max-statements": "off",
"max-statements-per-line": "warn",
"multiline-ternary": "off",
"new-cap": "warn",
"new-parens": "warn",
"newline-after-var": "off",
"newline-before-return": "off",
"newline-per-chained-call": "off",
"no-array-constructor": "warn",
"no-bitwise": "off",
"no-continue": "off",
"no-inline-comments": "off",
"no-lonely-if": "warn",
"no-mixed-operators": "off",
"no-mixed-spaces-and-tabs": "warn",
"no-multi-assign": "warn",
"no-multiple-empty-lines": ["warn", {
"maxBOF": 0,
"max": 1,
"maxEOF": 0,
}],
"no-negated-condition": "off",
"no-nested-ternary": "off",
"no-new-object": "warn",
"no-plusplus": "off",
"no-restricted-syntax": ["warn", {
"selector": "ForInStatement",
"message": "for-in loop used (did you mean to write a for-of loop?)",
}, {
"selector": "BinaryExpression[operator='in']",
"message": "in operator used (did you mean to call a membership-testing method?)",
}],
"no-tabs": "warn",
"no-ternary": "off",
"no-trailing-spaces": "warn",
"no-underscore-dangle": ["warn", {
"allowAfterThis": true,
"allowAfterSuper": true,
}],
"no-unneeded-ternary": "warn",
"no-whitespace-before-property": "warn",
"nonblock-statement-body-position": "off", // see curly
"object-curly-newline": "warn",
"object-curly-spacing": "warn",
"object-property-newline": "warn",
"one-var": ["warn", "never"],
"one-var-declaration-per-line": "warn",
"operator-assignment": "warn",
"operator-linebreak": "warn",
"padded-blocks": ["warn", "never"],
"quote-props": ["warn", "as-needed"],
"quotes": ["warn", "single"],
"require-jsdoc": "off",
"semi": "warn",
"semi-spacing": "warn",
"sort-keys": "off",
"sort-vars": "off",
"space-before-blocks": "off",
"space-before-function-paren": ["warn", "never"],
"space-in-parens": "warn",
"space-infix-ops": "warn",
"space-unary-ops": "warn",
"spaced-comment": "warn",
"template-tag-spacing": "off",
"unicode-bom": "warn",
"wrap-regex": "off",
"arrow-body-style": "warn",
"arrow-parens": "warn",
"arrow-spacing": "warn",
"constructor-super": "warn",
"generator-star-spacing": ["warn", "neither"],
"no-class-assign": "warn",
"no-confusing-arrow": "off",
"no-const-assign": "warn",
"no-dupe-class-members": "warn",
"no-duplicate-imports": "warn",
"no-new-symbol": "warn",
"no-restricted-imports": "off",
"no-this-before-super": "warn",
"no-useless-computed-key": "warn",
"no-useless-constructor": "warn",
"no-useless-rename": "warn",
"no-var": "warn",
"object-shorthand": "warn",
"prefer-arrow-callback": "warn",
"prefer-const": "warn",
"prefer-destructuring": "off",
"prefer-numeric-literals": "warn",
"prefer-rest-params": "warn",
"prefer-spread": "warn",
"prefer-template": "warn",
"require-yield": "warn",
"rest-spread-spacing": "warn",
"sort-imports": "off",
"symbol-description": "warn",
"template-curly-spacing": "warn",
"yield-star-spacing": "warn",
},
}
*~
.idea
{
"defaultSeverity": "warning",
"rules": {
"at-rule-empty-line-before": [ "always", {
except: [
"blockless-after-same-name-blockless",
"first-nested",
],
ignore: ["after-comment"],
} ],
"at-rule-name-case": "lower",
"at-rule-name-space-after": "always-single-line",
"at-rule-semicolon-newline-after": "always",
"block-closing-brace-empty-line-before": "never",
"block-closing-brace-newline-after": "always",
"block-closing-brace-newline-before": "always-multi-line",
"block-closing-brace-space-before": "always-single-line",
"block-no-empty": true,
"block-opening-brace-newline-after": "always-multi-line",
"block-opening-brace-space-after": "always-single-line",
"block-opening-brace-space-before": "always",
"color-hex-case": "lower",
"color-hex-length": "short",
"color-no-invalid-hex": true,
"comment-empty-line-before": [ "always", {
except: ["first-nested"],
ignore: ["stylelint-commands"],
} ],
"comment-no-empty": true,
"comment-whitespace-inside": "always",
"custom-property-empty-line-before": [ "always", {
except: [
"after-custom-property",
"first-nested",
],
ignore: [
"after-comment",
"inside-single-line-block",
],
} ],
"declaration-bang-space-after": "never",
"declaration-bang-space-before": "always",
"declaration-block-no-duplicate-properties": [ true, {
ignore: ["consecutive-duplicates-with-different-values"],
} ],
"declaration-block-no-redundant-longhand-properties": true,
"declaration-block-no-shorthand-property-overrides": true,
"declaration-block-semicolon-newline-after": "always-multi-line",
"declaration-block-semicolon-space-after": "always-single-line",
"declaration-block-semicolon-space-before": "never",
"declaration-block-single-line-max-declarations": 1,
"declaration-block-trailing-semicolon": "always",
"declaration-colon-newline-after": "always-multi-line",
"declaration-colon-space-after": "always-single-line",
"declaration-colon-space-before": "never",
"declaration-empty-line-before": [ "always", {
except: [
"after-declaration",
"first-nested",
],
ignore: [
"after-comment",
"inside-single-line-block",
],
} ],
"font-family-no-duplicate-names": true,
"function-calc-no-unspaced-operator": true,
"function-comma-newline-after": "always-multi-line",
"function-comma-space-after": "always-single-line",
"function-comma-space-before": "never",
"function-linear-gradient-no-nonstandard-direction": true,
"function-max-empty-lines": 0,
"function-name-case": "lower",
"function-parentheses-newline-inside": "always-multi-line",
"function-parentheses-space-inside": "never-single-line",
"function-whitespace-after": "always",
"indentation": 2,
"keyframe-declaration-no-important": true,
"length-zero-no-unit": true,
"max-empty-lines": 1,
"media-feature-colon-space-after": "always",
"media-feature-colon-space-before": "never",
"media-feature-name-case": "lower",
"media-feature-name-no-unknown": true,
"media-feature-parentheses-space-inside": "never",
"media-feature-range-operator-space-after": "always",
"media-feature-range-operator-space-before": "always",
"media-query-list-comma-newline-after": "always-multi-line",
"media-query-list-comma-space-after": "always-single-line",
"media-query-list-comma-space-before": "never",
"no-empty-source": true,
"no-eol-whitespace": true,
"no-extra-semicolons": true,
"no-invalid-double-slash-comments": true,
"no-missing-end-of-source-newline": true,
"number-leading-zero": "always",
"property-case": "lower",
"property-no-unknown": true,
"rule-empty-line-before": [ "always-multi-line", {
except: ["first-nested"],
ignore: ["after-comment"],
} ],
"selector-attribute-brackets-space-inside": "never",
"selector-attribute-operator-space-after": "never",
"selector-attribute-operator-space-before": "never",
"selector-combinator-space-after": "always",
"selector-combinator-space-before": "always",
"selector-descendant-combinator-no-non-space": true,
"selector-list-comma-newline-after": "always",
"selector-list-comma-space-before": "never",
"selector-max-empty-lines": 0,
"selector-pseudo-class-case": "lower",
"selector-pseudo-class-no-unknown": true,
"selector-pseudo-class-parentheses-space-inside": "never",
"selector-pseudo-element-case": "lower",
"selector-pseudo-element-colon-notation": "double",
"selector-pseudo-element-no-unknown": true,
"selector-type-case": "lower",
"selector-type-no-unknown": true,
"shorthand-property-no-redundant-values": true,
"string-no-newline": true,
"unit-case": "lower",
"unit-no-unknown": true,
"value-list-comma-newline-after": "always-multi-line",
"value-list-comma-space-after": "always-single-line",
"value-list-comma-space-before": "never",
"value-list-max-empty-lines": 0,
},
}
{
"ecmaVersion": 6,
"libs": [
"browser",
"jquery"
],
"loadEagerly": [],
"dontLoad": [
"node_module/**"
],
"plugins": {
"doc_comment": true,
"complete_strings": {
"maxLength": 15
}
}
}
\ No newline at end of file
p.rocket,
p.delta-v,
p.assessment {
white-space: pre-wrap;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Rocket Science</title>
<link rel="stylesheet" type="text/css" href="css/index.css">
</head>
<body>
<div id="human-design">
<h1>Human Design:</h1>
<p class="rocket"></p>
<p class="delta-v"></p>
<p class="assessment"></p>
</div>
<div id="computer-design">
<h1>Computer Design:</h1>
<p class="rocket"></p>
<p class="delta-v"></p>
<p class="assessment"></p>
</div>
<script src="libraries/jquery/jquery.min.js"></script>
<script src="js/priority_queue.js"></script>
<script src="js/rocket_science.js"></script>
<script src="js/index.js"></script>
</body>
</html>
/* globals Separator FuelTank Motor Stage Rocket designRocket */
/* eslint-disable no-magic-numbers */
function describeDeltaV(deltaV) {
if (deltaV >= 20000) {
return 'Mars';
}
if (deltaV >= 16000) {
return 'low Mars orbit';
}
if (deltaV >= 14600) {
return 'a Mars capture orbit';
}
if (deltaV >= 13700) {
return 'a Mars transfer orbit';
}
if (deltaV >= 9400) {
return 'low Earth orbit';
}
if (deltaV >= 1400) {
return 'the edge of space';
}
if (deltaV > 0) {
return 'suborbital flight';
}
return 'the launch pad (but not off of it)';
}
const EARTH_TO_SPACE_DELTA_V = 1400;
const EARTH_TO_LEO_DELTA_V = 9400;
const EARTH_TO_MARS_DELTA_V = 20000;
const PAYLOAD_MASS = 1000;
const SEPARATORS = [
new Separator(130, 3000),
new Separator(500, 24000),
new Separator(1000, 60000),
];
const FUEL_TANKS = [
new FuelTank(500, 1500),
new FuelTank(3000, 12000),
new FuelTank(4000, 50000),
];
const MOTORS = [
new Motor(20, 20, 150000),
new Motor(180, 70, 500000),
new Motor(850, 75, 700000),
];
const humanDesignedRocket = new Rocket(PAYLOAD_MASS, [
new Stage(1, SEPARATORS[0], FUEL_TANKS[0], MOTORS[2]),
new Stage(2, SEPARATORS[2], FUEL_TANKS[1], MOTORS[0]),
]);
$('#human-design .rocket').text(`${humanDesignedRocket}`);
$('#human-design .delta-v').text(`Effective Δv (accounting for fixed gravity): ${humanDesignedRocket.getEffectiveDeltaV()} m/s`);
$('#human-design .assessment').text(`This rocket can get to ${describeDeltaV(humanDesignedRocket.getEffectiveDeltaV())}.`);
const computerDesignedRocket = designRocket(PAYLOAD_MASS, SEPARATORS, FUEL_TANKS, MOTORS, EARTH_TO_LEO_DELTA_V); // EARTH_TO_SPACE_DELTA_V);
if (computerDesignedRocket !== undefined) {
$('#computer-design .rocket').text(`${computerDesignedRocket}`);
$('#computer-design .delta-v').text(`Effective Δv (accounting for fixed gravity): ${computerDesignedRocket.getEffectiveDeltaV()} m/s`);
$('#computer-design .assessment').text(`This rocket can get to ${describeDeltaV(computerDesignedRocket.getEffectiveDeltaV())}.`);
} else {
$('#computer-design .rocket').text('The computer failed to design a rocket.');
$('#computer-design .delta-v').text('Effective Δv (accounting for fixed gravity): N/A');
$('#computer-design .assessment').text('This rocket cannot even get onto the drawing board.');
}
/* exported PriorityQueue */
/* globals identity */
Array.prototype.indexOfMinimum = function indexOfMinimum(metric = identity) {
let index = undefined;
for (let i = this.length, minimum = Infinity; i--;) {
const measure = metric(this[i]);
if (measure <= minimum) {
index = i;
minimum = measure;
}
}
return index;
};
Array.prototype.remove = function remove(index) {
return index >= 0 ? this.splice(index, 1)[0] : undefined;
};
Array.prototype.delete = function(element) { // eslint-disable-line func-names, (reserved word)
this.remove(this.indexOf(element));
return this;
};
class PriorityQueue {
constructor(metric = identity) {
this.metric = metric;
this.elements = [];
}
_getNextIndex() {
return this.elements.indexOfMinimum(this.metric);
}
peek() {
const nextIndex = this._getNextIndex();
return nextIndex !== undefined ? this.elements[nextIndex] : undefined;
}
enqueue(element) {
this.elements.push(element);
}
dequeue() {
return this.elements.remove(this._getNextIndex());
}
delete(element) {
this.elements.delete(element);
}
}
/* exported Separator FuelTank Motor Stage Rocket designRocket */
/* globals PriorityQueue */
const EARTH_SURFACE_GRAVITY = 9.81;
class Separator {
constructor(mass, maximumLoad) {
this.mass = mass;
this.maximumLoad = maximumLoad;
}
toString() {
return `${this.mass} kg separator (${this.maximumLoad} kg max load)`;
}
}
class FuelTank {
constructor(dryMass, fuelMass) {
this.dryMass = dryMass;
this.fuelMass = fuelMass;
}
toString() {
return `${this.dryMass + this.fuelMass} kg fuel tank (${this.fuelMass} kg fuel)`;
}
}
class Motor {
constructor(mass, burnRate, thrust) {
this.mass = mass;
this.burnRate = burnRate;
this.thrust = thrust;
}
toString() {
return `${this.mass} kg motor (${this.thrust} N thrust)`;
}
}
class Stage {
constructor(count, separator, tank, motor) {
console.assert(separator.maximumLoad >= tank.dryMass + tank.fuelMass + motor.mass, `${separator} cannot support ${tank} and ${motor}`);
this.count = count;
this.separator = separator;
this.tank = tank;
this.motor = motor;
}
get dryMass() {
return this.count * (this.separator.mass + this.tank.dryMass + this.motor.mass);
}
get fuelMass() {
return this.count * this.tank.fuelMass;
}
get wetMass() {
return this.count * (this.separator.mass + this.tank.dryMass + this.tank.fuelMass + this.motor.mass);
}
get burnRate() {
return this.count * this.motor.burnRate;
}
get thrust() {
return this.count * this.motor.thrust;
}
getEffectiveDeltaV(payloadMass, gravity = EARTH_SURFACE_GRAVITY) {
const effectiveDryMass = payloadMass + this.dryMass;
const effectiveWetMass = effectiveDryMass + this.fuelMass;
return (this.thrust * (Math.log(effectiveWetMass) - Math.log(effectiveDryMass)) - gravity * this.fuelMass) / this.burnRate;
}
toString() {
return `${this.count}✕ [${this.separator}, ${this.tank}, and ${this.motor}]`;
}
}
class Rocket {
constructor(payloadMass, stages) { // stages should be given in reverse order of firing
this.payloadMass = payloadMass;
this.stages = stages;
}
get mass() {
let result = this.payloadMass;
for (const stage of this.stages) {
result += stage.wetMass;
}
return result;
}
getEffectiveDeltaV(gravity = EARTH_SURFACE_GRAVITY) {
let result = 0;
let stagePayloadMass = this.payloadMass;
for (const stage of this.stages) {
result += stage.getEffectiveDeltaV(stagePayloadMass, gravity);
stagePayloadMass += stage.wetMass;
}
return result;
}
toString() {
let result = `${this.mass} kg, ${this.stages.length}-stage rocket:\n ${this.payloadMass} kg payload`;
for (const stage of this.stages) {
result += `\n ← ${stage}`;
}
return result;
}
}
function designRocket(payloadMass, separators, tanks, motors, targetDeltaV, gravity = EARTH_SURFACE_GRAVITY) {
return undefined; // TODO: stub
}
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment