├── .gitignore ├── Season1 ├── make │ ├── make_demo │ │ ├── src │ │ │ └── app.js │ │ ├── dist │ │ │ └── app.js │ │ └── Makefile │ └── web │ │ ├── assets │ │ ├── js │ │ │ ├── cart.js │ │ │ ├── checkout.js │ │ │ ├── thing │ │ │ │ └── thing.js │ │ │ └── app.js │ │ └── sass │ │ │ └── main.scss │ │ ├── public │ │ ├── css │ │ │ └── app.css │ │ └── js │ │ │ └── app.js │ │ ├── package.json │ │ └── Makefile ├── patterns │ ├── creational │ │ ├── cart.js │ │ ├── constructor.js │ │ ├── singleton.js │ │ ├── factory.js │ │ ├── builder.js │ │ ├── method_chaining.js │ │ └── singleton.cs │ ├── structural │ │ ├── lib │ │ │ ├── sales.js │ │ │ ├── cart.js │ │ │ ├── repository.js │ │ │ └── poolable.js │ │ ├── adapter.js │ │ ├── bridge.js │ │ ├── decorator.js │ │ ├── flyweight.js │ │ ├── facade.js │ │ └── composite.js │ └── behavioral │ │ ├── observer.js │ │ ├── command.js │ │ ├── mediator.js │ │ ├── state.js │ │ ├── strategy.js │ │ └── chain_of_responsibility.js ├── scripts │ ├── dist │ │ ├── ace.jpg │ │ ├── 3nf2.png │ │ ├── gc-1.png │ │ ├── gc-2.png │ │ ├── lex-1.png │ │ ├── ae_plan.jpg │ │ ├── calc_mac.png │ │ ├── calculator.jpg │ │ ├── snowflake.png │ │ ├── difference_engine.jpg │ │ ├── 17071818163_66adaafda2_k.0.jpg │ │ ├── 17504334828_6d727a0ecf_k.0.jpg │ │ └── 17504602910_a939b425ba_k.0.jpg │ ├── images │ │ ├── doodles │ │ │ ├── 3nf2.png │ │ │ ├── gc-1.png │ │ │ ├── gc-2.png │ │ │ ├── lex-1.png │ │ │ └── snowflake.png │ │ ├── screenshots │ │ │ ├── ace.jpg │ │ │ ├── ae_plan.jpg │ │ │ ├── calc_mac.png │ │ │ ├── calculator.jpg │ │ │ └── difference_engine.jpg │ │ └── space │ │ │ ├── 17071818163_66adaafda2_k.0.jpg │ │ │ ├── 17504334828_6d727a0ecf_k.0.jpg │ │ │ └── 17504602910_a939b425ba_k.0.jpg │ ├── resizer.sh │ └── jekyll_post.sh ├── normalizing │ ├── 00_create_db.sql │ ├── 01_import_data.sql │ ├── 02_first_nf.sql │ ├── 05_ref_integrity.sql │ ├── 04_third_nf.sql │ └── 03_second_nf.sql ├── functional │ ├── package.json │ ├── purity_and_se.js │ ├── immutability.exs │ ├── currying.js │ └── monad.js ├── algorithms │ ├── dynamic_programming │ │ ├── fib.js │ │ ├── sieve.js │ │ ├── bellman-ford.js │ │ └── dijkstra.js │ └── simple │ │ ├── binary_search.js │ │ ├── quicksort.js │ │ ├── bubble_sort.js │ │ ├── selection_sort.js │ │ └── merge_sort.js ├── testing │ ├── bdd │ │ └── billing_spec.js │ └── tdd │ │ └── billing_test.js └── design_principles │ ├── solid │ ├── interface_seg.cs │ ├── basis.js │ └── dependency_inversion.cs │ ├── coupling.js │ ├── cohesion.js │ ├── dependency_injection.js │ ├── tell_dont_ask.js │ └── law_of_demeter.js ├── Season2 ├── 07-encryption │ ├── .env │ ├── package.json │ ├── ciphers │ │ ├── dhm.js │ │ ├── caeser.js │ │ ├── alphabet.js │ │ └── onetimepad.js │ ├── lib │ │ ├── spy.js │ │ └── bad_guy.js │ ├── test │ │ ├── one_time_pads.js │ │ ├── diffie_helman.js │ │ └── simple_encryption.js │ ├── data │ │ └── pads.js │ └── package-lock.json ├── 08-hashes │ ├── message.txt │ ├── crypto.js │ ├── package.json │ ├── hashes.js │ ├── blockchain.js │ ├── rsa.js │ └── package-lock.json ├── 01-binary-math │ ├── package.json │ └── addition.js ├── 02-bitwise │ ├── basics.js │ ├── package.json │ ├── package-lock.json │ └── addition.js ├── 04-entropy │ ├── hartley.js │ └── shannon.js ├── 05-encoding │ ├── package.json │ ├── lovebug.js │ ├── encoder.js │ ├── lib │ │ ├── encoding.js │ │ └── shannon.js │ ├── tale_of_two_cities.txt │ └── index.js ├── 06-error-correction │ ├── package.json │ ├── index.js │ ├── parity.js │ ├── encoder_1.js │ ├── encoder.js │ └── hamming.js ├── 062-error-correction │ ├── package.json │ ├── index.js │ ├── encoder.js │ └── hamming.js ├── 00-boolean-algebra │ ├── package.json │ ├── math.js │ ├── package-lock.json │ └── operations.js └── 03-negation │ ├── subtraction-bitwise.js │ └── subtraction.js ├── .github ├── code-bug.md └── video-issue.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | -------------------------------------------------------------------------------- /Season1/make/make_demo/src/app.js: -------------------------------------------------------------------------------- 1 | //some code 2 | -------------------------------------------------------------------------------- /Season2/07-encryption/.env: -------------------------------------------------------------------------------- 1 | alias run="mocha --recursive" -------------------------------------------------------------------------------- /Season1/make/make_demo/dist/app.js: -------------------------------------------------------------------------------- 1 | //Created at 2017-February-15 2 | 3 | 4 | //some code 5 | -------------------------------------------------------------------------------- /Season1/patterns/creational/cart.js: -------------------------------------------------------------------------------- 1 | //Only one cart for everybody! 2 | exports.items = []; 3 | -------------------------------------------------------------------------------- /Season1/make/web/assets/js/cart.js: -------------------------------------------------------------------------------- 1 | App.Cart = function(){ 2 | console.log("Buy some stuff!"); 3 | }; 4 | -------------------------------------------------------------------------------- /Season1/make/web/assets/js/checkout.js: -------------------------------------------------------------------------------- 1 | App.Checkout = function(){ 2 | console.log("Checking out!"); 3 | }; 4 | -------------------------------------------------------------------------------- /Season1/make/web/assets/js/thing/thing.js: -------------------------------------------------------------------------------- 1 | App.Checkout = function(){ 2 | console.log("PPuke on you"); 3 | }; 4 | -------------------------------------------------------------------------------- /Season1/scripts/dist/ace.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/dist/ace.jpg -------------------------------------------------------------------------------- /Season1/scripts/dist/3nf2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/dist/3nf2.png -------------------------------------------------------------------------------- /Season1/scripts/dist/gc-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/dist/gc-1.png -------------------------------------------------------------------------------- /Season1/scripts/dist/gc-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/dist/gc-2.png -------------------------------------------------------------------------------- /Season1/scripts/dist/lex-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/dist/lex-1.png -------------------------------------------------------------------------------- /Season1/scripts/dist/ae_plan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/dist/ae_plan.jpg -------------------------------------------------------------------------------- /Season1/scripts/dist/calc_mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/dist/calc_mac.png -------------------------------------------------------------------------------- /Season1/scripts/dist/calculator.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/dist/calculator.jpg -------------------------------------------------------------------------------- /Season1/scripts/dist/snowflake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/dist/snowflake.png -------------------------------------------------------------------------------- /Season1/normalizing/00_create_db.sql: -------------------------------------------------------------------------------- 1 | -- the DB we'll be working with 2 | drop database if exists rentals; 3 | create database rentals; 4 | -------------------------------------------------------------------------------- /Season1/scripts/images/doodles/3nf2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/images/doodles/3nf2.png -------------------------------------------------------------------------------- /Season1/scripts/images/doodles/gc-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/images/doodles/gc-1.png -------------------------------------------------------------------------------- /Season1/scripts/images/doodles/gc-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/images/doodles/gc-2.png -------------------------------------------------------------------------------- /Season1/scripts/images/doodles/lex-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/images/doodles/lex-1.png -------------------------------------------------------------------------------- /Season2/08-hashes/message.txt: -------------------------------------------------------------------------------- 1 | You want a toe? I can get you a toe, believe me. There are ways, Dude. You don't wanna know about it, believe me. -------------------------------------------------------------------------------- /Season1/scripts/dist/difference_engine.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/dist/difference_engine.jpg -------------------------------------------------------------------------------- /Season1/scripts/images/screenshots/ace.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/images/screenshots/ace.jpg -------------------------------------------------------------------------------- /Season1/scripts/images/doodles/snowflake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/images/doodles/snowflake.png -------------------------------------------------------------------------------- /Season1/scripts/images/screenshots/ae_plan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/images/screenshots/ae_plan.jpg -------------------------------------------------------------------------------- /Season1/scripts/images/screenshots/calc_mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/images/screenshots/calc_mac.png -------------------------------------------------------------------------------- /Season1/make/web/assets/js/app.js: -------------------------------------------------------------------------------- 1 | var App = { 2 | storeName : "Amazing Place" 3 | }; 4 | 5 | App.sayHello = function(){ 6 | console.log("Hi there"); 7 | } 8 | -------------------------------------------------------------------------------- /Season1/scripts/dist/17071818163_66adaafda2_k.0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/dist/17071818163_66adaafda2_k.0.jpg -------------------------------------------------------------------------------- /Season1/scripts/dist/17504334828_6d727a0ecf_k.0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/dist/17504334828_6d727a0ecf_k.0.jpg -------------------------------------------------------------------------------- /Season1/scripts/dist/17504602910_a939b425ba_k.0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/dist/17504602910_a939b425ba_k.0.jpg -------------------------------------------------------------------------------- /Season1/scripts/images/screenshots/calculator.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/images/screenshots/calculator.jpg -------------------------------------------------------------------------------- /Season1/scripts/images/screenshots/difference_engine.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/images/screenshots/difference_engine.jpg -------------------------------------------------------------------------------- /Season1/scripts/images/space/17071818163_66adaafda2_k.0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/images/space/17071818163_66adaafda2_k.0.jpg -------------------------------------------------------------------------------- /Season1/scripts/images/space/17504334828_6d727a0ecf_k.0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/images/space/17504334828_6d727a0ecf_k.0.jpg -------------------------------------------------------------------------------- /Season1/scripts/images/space/17504602910_a939b425ba_k.0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imposters-handbook/videos/HEAD/Season1/scripts/images/space/17504602910_a939b425ba_k.0.jpg -------------------------------------------------------------------------------- /Season1/make/web/public/css/app.css: -------------------------------------------------------------------------------- 1 | body{font:100% Helvetica,sans-serif;color:#333}.box{-webkit-border-radius:10px;-moz-border-radius:10px;-ms-border-radius:10px;border-radius:10px} 2 | -------------------------------------------------------------------------------- /Season1/make/web/public/js/app.js: -------------------------------------------------------------------------------- 1 | var App={storeName:"Amazing Place"};App.sayHello=function(){console.log("Hi there")};App.Cart=function(){console.log("Buy some stuff!")};App.Checkout=function(){console.log("Checking out!")}; -------------------------------------------------------------------------------- /Season2/01-binary-math/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "01-binary-math", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "ascii-table": "^0.0.9" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Season2/02-bitwise/basics.js: -------------------------------------------------------------------------------- 1 | const A = 0b11011; 2 | const B = 0b1111; 3 | 4 | //the basics 5 | console.log(A === 27) 6 | console.log(B === 15) 7 | 8 | //XOR - tells us nothing on its own 9 | console.log(A ^ B) //20 10 | console.log(A & B) //11 11 | -------------------------------------------------------------------------------- /Season2/04-entropy/hartley.js: -------------------------------------------------------------------------------- 1 | //the idea here is to calculate the entropy for a given message 2 | //it's in base 10 3 | 4 | const H = (m) => { 5 | const possibleMessages = Math.pow(36,m.length); 6 | return Math.log(possibleMessages) 7 | } 8 | 9 | console.log(H("hello")); -------------------------------------------------------------------------------- /Season1/patterns/structural/lib/sales.js: -------------------------------------------------------------------------------- 1 | const ShoppingCart = require("./cart"); 2 | const PgAdapter = require("../bridge"); 3 | const SalesRepository = require("./repository"); 4 | 5 | const repo = new SalesRepository(PgAdapter); 6 | //get a cart by key? 7 | repo.fetchCarts("test"); 8 | -------------------------------------------------------------------------------- /Season2/05-encoding/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "05-encoding", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC" 11 | } 12 | -------------------------------------------------------------------------------- /Season1/scripts/resizer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | IMAGES=$(ls ./images/**/*.jpg ./images/**/*.png) 3 | DIST=./dist 4 | 5 | if [ -d "$DIST" ]; then 6 | rm -R "$DIST" 7 | fi 8 | 9 | mkdir "$DIST" 10 | 11 | for IMG in $IMAGES 12 | do 13 | convert $IMG -resize 600x400 "$DIST/$(basename $IMG)" 14 | done 15 | -------------------------------------------------------------------------------- /Season2/06-error-correction/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "06-error-correction", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC" 11 | } 12 | -------------------------------------------------------------------------------- /Season2/062-error-correction/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "06-error-correction", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC" 11 | } 12 | -------------------------------------------------------------------------------- /.github/code-bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Code Bug 3 | about: Found a problem with the code in the videos? 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## I think this code is wrong/doesn't work: 11 | 12 | ```js 13 | 14 | ``` 15 | 16 | ## When I change it to this things are better: 17 | 18 | ```js 19 | 20 | ``` 21 | -------------------------------------------------------------------------------- /Season2/02-bitwise/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "02-bitwise", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "addition.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "ascii-table": "0.0.9" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Season2/08-hashes/crypto.js: -------------------------------------------------------------------------------- 1 | const crypto = require("crypto"); 2 | const fs = require("fs"); 3 | 4 | const data = fs.readFileSync("./message.txt"); 5 | 6 | const checksum = function(data){ 7 | return crypto.createHash("md5").update(data, "utf8").digest("hex") 8 | } 9 | 10 | console.log(checksum(data)); 11 | 12 | //77bc97770feefd2f20600bb3d34a455b -------------------------------------------------------------------------------- /Season2/07-encryption/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "07-encryption", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha --recursive" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mocha": "^8.2.1", 13 | "vigenere": "^1.0.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Season1/patterns/creational/constructor.js: -------------------------------------------------------------------------------- 1 | //Constructor: creating a simple instance 2 | class ShoppingCart{ 3 | constructor({items: items} = {items: []}){ 4 | //set some values 5 | //validations and rules for creating an object 6 | //like: need to have items! 7 | this.items = items; 8 | } 9 | } 10 | 11 | console.log(new ShoppingCart()); 12 | -------------------------------------------------------------------------------- /Season2/00-boolean-algebra/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "00-boolean-algebra", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "operations.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "ascii-table": "0.0.9" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Season1/make/web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "node-sass": "^4.5.0", 13 | "uglifyjs": "^2.4.10" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Season1/patterns/structural/lib/cart.js: -------------------------------------------------------------------------------- 1 | const assert = require("assert"); 2 | class ShoppingCart{ 3 | constructor(key){ 4 | assert(key, "A key is required"); 5 | this.key = key; 6 | this.items = []; 7 | this.createdAt = new Date(); 8 | }; 9 | addItem(item){ 10 | this.items.push(item); 11 | return this; 12 | } 13 | } 14 | module.exports = ShoppingCart; 15 | -------------------------------------------------------------------------------- /Season2/00-boolean-algebra/math.js: -------------------------------------------------------------------------------- 1 | var AsciiTable = require('ascii-table'); 2 | 3 | const truthTable = (op) => { 4 | const tbl = new AsciiTable(`${op}`) 5 | tbl 6 | .setHeading("X", "Y", "Out") 7 | .addRow(0, 0, "00") 8 | .addRow(0, 1, "01") 9 | .addRow(1, 0, "01") 10 | .addRow(1, 1, "10"); 11 | console.log(tbl.toString()); 12 | }; 13 | 14 | truthTable("ADDITION") -------------------------------------------------------------------------------- /Season2/02-bitwise/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "02-bitwise", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ascii-table": { 8 | "version": "0.0.9", 9 | "resolved": "https://registry.npmjs.org/ascii-table/-/ascii-table-0.0.9.tgz", 10 | "integrity": "sha1-BqZgTWpV1L9BqaR9mHLXp42jHnM=" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Season1/functional/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "immutability", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "es6.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "lodash": "^4.17.4", 13 | "pg-promise": "^5.5.2", 14 | "ramda": "^0.23.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Season2/00-boolean-algebra/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "00-boolean-algebra", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ascii-table": { 8 | "version": "0.0.9", 9 | "resolved": "https://registry.npmjs.org/ascii-table/-/ascii-table-0.0.9.tgz", 10 | "integrity": "sha1-BqZgTWpV1L9BqaR9mHLXp42jHnM=" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Season1/normalizing/01_import_data.sql: -------------------------------------------------------------------------------- 1 | --create the table and import the CSV file 2 | drop table if exists rental_import; 3 | create table rental_import( 4 | customer varchar(255), 5 | email varchar(255), 6 | rental_number varchar(50), 7 | total varchar(50), 8 | rental_date varchar(50), 9 | items text 10 | ); 11 | COPY rental_import FROM 12 | '[ABS PATH TO RENTALS CSV IN THIS DIR]' 13 | DELIMITER ',' CSV; 14 | -------------------------------------------------------------------------------- /Season1/make/make_demo/Makefile: -------------------------------------------------------------------------------- 1 | JS_FILES=src/app.js 2 | DIST=dist 3 | BUILD=$(DIST)/app.js 4 | TODAY=$(shell date +%Y-%B-%d) 5 | TIMESTAMP="//Created at $(TODAY) \n\n" 6 | 7 | all: $(BUILD) 8 | 9 | $(BUILD): $(DIST) timestamp 10 | @ cat $(JS_FILES) >> $@ 11 | 12 | timestamp: 13 | @ echo $(TIMESTAMP) > $(BUILD) 14 | 15 | $(DIST): 16 | @ mkdir -p $@ 17 | 18 | clean: 19 | @ rm -R $(DIST) 20 | 21 | 22 | .PHONY: clean 23 | -------------------------------------------------------------------------------- /Season1/patterns/creational/singleton.js: -------------------------------------------------------------------------------- 1 | //Singleton: returns only a single instance of an object 2 | //is almost always a bad idea 3 | const ShoppingCart = require("./cart"); 4 | const OtherCart = require("./Cart"); 5 | 6 | //BAHAHAHAHAHAHA SUBVERSION! 7 | 8 | ShoppingCart.items.push({sku: "SOCKS"}) 9 | OtherCart.items.push({sku: "More SOCKS"}) 10 | 11 | console.log(OtherCart.items); 12 | console.log(ShoppingCart.items); 13 | -------------------------------------------------------------------------------- /Season1/patterns/structural/adapter.js: -------------------------------------------------------------------------------- 1 | class PgAdapter{ 2 | constructor(){ 3 | this.name = "Postgres Adapter" 4 | }; 5 | save(item){ 6 | console.log("Saving to PG"); 7 | }; 8 | } 9 | class RedisAdapter{ 10 | constructor(){ 11 | this.name = "Redis Adapter" 12 | }; 13 | save(item){ 14 | console.log("Saving to Redis"); 15 | }; 16 | } 17 | exports.pg = PgAdapter; 18 | exports.redis = RedisAdapter; 19 | -------------------------------------------------------------------------------- /Season1/make/web/assets/sass/main.scss: -------------------------------------------------------------------------------- 1 | $font-stack: Helvetica, sans-serif; 2 | $primary-color: #333; 3 | 4 | body { 5 | font: 100% $font-stack; 6 | color: $primary-color; 7 | } 8 | 9 | @mixin border-radius($radius) { 10 | -webkit-border-radius: $radius; 11 | -moz-border-radius: $radius; 12 | -ms-border-radius: $radius; 13 | border-radius: $radius; 14 | } 15 | 16 | .box { @include border-radius(10px); } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Code For The Imposter's Handbook Videos, Seasons 1 and 2 2 | 3 | This is the code for the "CS Basics" video series, otherwise known as "The Imposter Video Series". They started out as individual offerings but in late 2020 I combined them into a single video set [which you can see more of right here](https://bigmachine.io/productions/imposter-video). 4 | 5 | If you have any issues with the code or videos, feel free to leave an issue! 6 | -------------------------------------------------------------------------------- /Season2/02-bitwise/addition.js: -------------------------------------------------------------------------------- 1 | //a fine interview answer 2 | const add = function (x, y) { 3 | //Iterate till there is no carry 4 | let should_carry = null; 5 | while(should_carry !== 0){ 6 | should_carry = x & y; 7 | x = x ^ y; 8 | y = should_carry << 1 9 | } 10 | return x; 11 | } 12 | 13 | //One-liner because... they're fun 14 | const addX = (x, y) => y === 0 ? x : add((x ^ y), (x & y) << 1); 15 | 16 | console.log(add(27,15)) -------------------------------------------------------------------------------- /Season1/algorithms/dynamic_programming/fib.js: -------------------------------------------------------------------------------- 1 | //Fibonacci with Dynamic Programming 2 | const calculateFibAt = (n) =>{ 3 | var memoTable = [0,1]; 4 | for(var i=2;i<=n;i++){ 5 | memoTable.push(memoTable[i-2] + memoTable[i-1]) 6 | } 7 | return memoTable; 8 | }; 9 | console.log(calculateFibAt(1000)); 10 | 11 | 12 | //slow, recursive way 13 | const fibSlow = n => n < 2 ? n : fibSlow(n-2) + fibSlow(n-1); 14 | 15 | console.log(fibSlow(10)); 16 | -------------------------------------------------------------------------------- /Season2/07-encryption/ciphers/dhm.js: -------------------------------------------------------------------------------- 1 | class DiffieHellman{ 2 | constructor({generator, secret, modulus}={}){ 3 | this.generator = generator; 4 | this.secret = secret; 5 | this.modulus = modulus; 6 | this.publicKey = Math.pow(this.generator,this.secret) % this.modulus; 7 | } 8 | encryptionKey(receiverPublicKey){ 9 | return Math.pow(receiverPublicKey, this.secret) % this.modulus; 10 | } 11 | } 12 | module.exports = DiffieHellman; 13 | 14 | -------------------------------------------------------------------------------- /Season2/08-hashes/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "08-hashes", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "bcryptjs": "^2.4.3", 14 | "pg-promise": "^10.8.6", 15 | "pg-query-stream": "^4.0.0", 16 | "scrypt-js": "^3.0.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Season1/algorithms/simple/binary_search.js: -------------------------------------------------------------------------------- 1 | const list = [4,8,15,16,23,42]; 2 | 3 | const binarySearch = (list, lookFor) => { 4 | var min=0, max=list.length; 5 | var middle; 6 | while(min <= max){ 7 | middle = Math.floor((min + max) / 2); 8 | if(list[middle] === lookFor){ 9 | return middle; 10 | }else{ 11 | list[middle] < lookFor ? min=middle : max=middle; 12 | } 13 | } 14 | return -1; 15 | }; 16 | console.log(binarySearch(list,45)); 17 | -------------------------------------------------------------------------------- /Season1/patterns/creational/factory.js: -------------------------------------------------------------------------------- 1 | //Factory: a formalized way to construct an object 2 | class ShoppingCart{} 3 | ShoppingCart.fromDefaults = () => { 4 | var cart = new ShoppingCart(); 5 | cart.createdAt = new Date(); 6 | cart.items = []; 7 | return cart; 8 | } 9 | ShoppingCart.withItems = (items = []) => { 10 | var cart = new ShoppingCart(); 11 | cart.createdAt = new Date(); 12 | cart.items = items; 13 | return cart; 14 | } 15 | console.log(ShoppingCart.withItems([{sku: "SOCKS"}])); 16 | -------------------------------------------------------------------------------- /Season1/patterns/structural/bridge.js: -------------------------------------------------------------------------------- 1 | //Bridge: abstracting the interface 2 | const CartRetrieval = (db) => { 3 | return { 4 | get: (id) => console.log(`Getting from ${db.name}`), 5 | fetch: (id) => console.log(`Fetching from ${db.name}`) 6 | } 7 | } 8 | class PgAdapter{ 9 | constructor(){ 10 | this.name = "Postgres Adapter"; 11 | this.cart = CartRetrieval(this); 12 | }; 13 | save(item){ 14 | console.log("Saving to PG"); 15 | }; 16 | } 17 | module.exports = new PgAdapter(); 18 | -------------------------------------------------------------------------------- /Season1/patterns/structural/decorator.js: -------------------------------------------------------------------------------- 1 | //Decorator: an alternative to Bridge that builds functionality 2 | //directly onto an object 3 | const poolable = require("./lib/poolable"); 4 | 5 | class PgAdapter{ 6 | constructor(connectionString){ 7 | this.connectionString = connectionString; 8 | this.name = "Postgres Adapter"; 9 | }; 10 | save(item){ 11 | console.log("Saving to PG"); 12 | }; 13 | } 14 | 15 | 16 | const adapter = poolable(new PgAdapter("test"), 10); 17 | console.log(adapter); 18 | -------------------------------------------------------------------------------- /Season1/normalizing/02_first_nf.sql: -------------------------------------------------------------------------------- 1 | --1 NF: Values in cells must be atomic 2 | drop table if exists rental_first_nf; 3 | with source as ( 4 | select *, 5 | trim(regexp_split_to_table(items, E',')) as item 6 | from rental_import 7 | ), fixed as ( 8 | select customer, email, rental_number, total::money, rental_date::date, 9 | split_part(item, ';',1) as title, 10 | split_part(item, ';',2) as rating, 11 | split_part(item, ';',3)::money as fee 12 | from source 13 | ) 14 | select * into rental_first_nf from fixed; 15 | -------------------------------------------------------------------------------- /Season1/patterns/structural/lib/repository.js: -------------------------------------------------------------------------------- 1 | const ShoppingCart = require("./cart"); 2 | class SalesRepository{ 3 | constructor(adapter){ 4 | this.db = adapter; 5 | }; 6 | saveCart(cart){ 7 | //db interaction... 8 | this.db.save(cart); 9 | console.log(`Cart ${cart.key} saved to ${this.db.name}`); 10 | }; 11 | getCart(key){ 12 | return this.db.cart.get(key); 13 | }; 14 | fetchCarts(){ 15 | return this.db.cart.fetch(); 16 | } 17 | } 18 | 19 | module.exports = SalesRepository; 20 | -------------------------------------------------------------------------------- /Season1/algorithms/simple/quicksort.js: -------------------------------------------------------------------------------- 1 | const list = [23,4,42,8,16,15]; 2 | const quickSort = (list) => { 3 | if(list.length < 2) return list; 4 | var left=[], right=[]; 5 | const pivot = list.length -1; 6 | const pivotValue = list[pivot]; 7 | list = list.slice(0,pivot).concat(list.slice(pivot + 1)); 8 | for (var item in list) { 9 | item < pivotValue ? left.push(item) : right.push(item); 10 | } 11 | return quickSort(left).concat([pivotValue], quickSort(right)); 12 | }; 13 | 14 | console.log(quickSort(list)); 15 | -------------------------------------------------------------------------------- /Season1/algorithms/dynamic_programming/sieve.js: -------------------------------------------------------------------------------- 1 | //Sieve of Eratosthenes 2 | const sieve = (n) => { 3 | var grid = {}; 4 | for (var i = 2; i <= n; i++) { 5 | grid[i]={marked: false}; 6 | } 7 | const limit = Math.sqrt(n); 8 | for (var i = 2; i <= limit; i++) { 9 | for(var x = i + i; x <= n; x += i){ 10 | grid[x].marked = true; 11 | } 12 | } 13 | var out =[]; 14 | for (var i = 2; i <= n; i++) { 15 | if(!grid[i].marked) out.push(i); 16 | } 17 | return out; 18 | }; 19 | console.log(sieve(100)); 20 | -------------------------------------------------------------------------------- /Season2/07-encryption/lib/spy.js: -------------------------------------------------------------------------------- 1 | 2 | class Spy{ 3 | constructor({cipher=null}){ 4 | this.cipher = cipher; 5 | this.receivedMessage=null; 6 | this.sentMessage=null; 7 | } 8 | send(message, to){ 9 | const encryptedMessage = this.cipher.encrypt(message); 10 | this.sentMessage = encryptedMessage; 11 | to.receive(encryptedMessage); 12 | } 13 | receive(encryptedMessage){ 14 | const decryptedMessage = this.cipher.decrypt(encryptedMessage); 15 | this.receivedMessage = decryptedMessage; 16 | } 17 | } 18 | 19 | module.exports = Spy; -------------------------------------------------------------------------------- /Season1/normalizing/05_ref_integrity.sql: -------------------------------------------------------------------------------- 1 | update rentals set 2 | customer_id = (select id from customers where email = rentals.email), 3 | film_id = (select id from films where title = rentals.film_title); 4 | 5 | alter table rentals 6 | drop constraint if exists rental_customers; 7 | 8 | alter table rentals 9 | drop constraint if exists rental_films; 10 | 11 | alter table rentals 12 | add constraint rental_customers 13 | foreign key (customer_id) references customers(id); 14 | 15 | alter table rentals 16 | add constraint rental_films 17 | foreign key (film_id) references films(id); 18 | -------------------------------------------------------------------------------- /.github/video-issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Video Problem 3 | about: Found a non-code problem? Thanks for letting me know! 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Where'd you see it? The video name/timestamp would be super helpful 11 | 12 | ## What's the problem? 13 | 14 | This is what I saw: 15 | ```md 16 | //put it in here 17 | ``` 18 | 19 | This is what I think it should be: 20 | ```md 21 | //put it in here 22 | ``` 23 | 24 | ## How are you watching the video? 25 | 26 | Please let me know if you're streaming it or, if you downloaded, what your player is. 27 | -------------------------------------------------------------------------------- /Season1/patterns/creational/builder.js: -------------------------------------------------------------------------------- 1 | //Builder: a more formalized way of creating an object 2 | class ShoppingCart{}; 3 | class ShoppingCartBuilder{ 4 | constructor(){ 5 | this.cart = new ShoppingCart(); 6 | }; 7 | setCreationDate(date){ 8 | this.cart.createdAt = date; 9 | }; 10 | setItems(items){ 11 | this.cart.items = items; 12 | }; 13 | build(){ 14 | return this.cart; 15 | }; 16 | }; 17 | var builder = new ShoppingCartBuilder(); 18 | builder.setCreationDate(new Date()); 19 | builder.setItems([]); 20 | var cart = builder.build(); 21 | console.log(cart); 22 | -------------------------------------------------------------------------------- /Season1/algorithms/simple/bubble_sort.js: -------------------------------------------------------------------------------- 1 | const list = [23,4,42,15,16,8]; 2 | const bubbleSort = (list) => { 3 | var doItAgain = false; 4 | const limit = list.length; 5 | const defaultNextVal = Number.POSITIVE_INFINITY; 6 | for (var i = 0; i < limit; i++) { 7 | let thisValue = list[i]; 8 | let nextValue = i + 1 < limit ? list[i+1] : defaultNextVal; 9 | if(nextValue < thisValue){ 10 | list[i] = nextValue; 11 | list[i+1] = thisValue; 12 | doItAgain = true; 13 | } 14 | } 15 | if(doItAgain) bubbleSort(list); 16 | } 17 | bubbleSort(list); 18 | console.log(list); 19 | -------------------------------------------------------------------------------- /Season2/07-encryption/ciphers/caeser.js: -------------------------------------------------------------------------------- 1 | 2 | const offsetChars = (text, offset=1) => { 3 | const out = []; 4 | for(let i=0; i < text.length; i++){ 5 | const offsetIndex = text.charCodeAt(i) + offset; 6 | out.push(String.fromCharCode(offsetIndex)) 7 | } 8 | return out.join(""); 9 | } 10 | 11 | class Caesar { 12 | constructor(offset=5){ 13 | this.offset=offset; 14 | } 15 | encrypt(plainText){ 16 | return offsetChars(plainText, this.offset); 17 | } 18 | decrypt(cipherText){ 19 | return offsetChars(cipherText, -this.offset); 20 | } 21 | } 22 | module.exports = Caesar; -------------------------------------------------------------------------------- /Season1/algorithms/simple/selection_sort.js: -------------------------------------------------------------------------------- 1 | const list = [23,4,42,8,16,15]; 2 | const selectionSort = (list) => { 3 | for (var i = 0; i < list.length; i++) { 4 | var currentMinIndex = i; 5 | for(var x = currentMinIndex + 1; x < list.length; x++){ 6 | if(list[x] < list[currentMinIndex]){ 7 | currentMinIndex = x; 8 | } 9 | } 10 | if(currentMinIndex != i){ 11 | var oldMinValue = list[i]; 12 | list[i] = list[currentMinIndex]; 13 | list[currentMinIndex] = oldMinValue; 14 | } 15 | } 16 | return list; 17 | }; 18 | console.log(selectionSort(list)); 19 | -------------------------------------------------------------------------------- /Season1/testing/bdd/billing_spec.js: -------------------------------------------------------------------------------- 1 | //BDD: Focus on behavior 2 | describe("Monthly Billing", function(){ 3 | describe("Payment received", function(){ 4 | it("an invoice is created"); 5 | it("subscription status is set to active"); 6 | it("next billing is set to 1 month from now"); 7 | it("a notice is sent to the customer"); 8 | }); 9 | describe("Payment fails", function(){ 10 | it("an invoice is not created"); 11 | it("subscription status is set to retry"); 12 | it("next billing is set to 1 day from now"); 13 | it("a notice is sent to the customer"); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /Season1/functional/purity_and_se.js: -------------------------------------------------------------------------------- 1 | //purity: a function takes in what it needs, returns a value 2 | //side effects: affecting the state of something outside the current function scope 3 | 4 | //pure code 5 | //easy to test and to debug 6 | const squareIt = (num) => { 7 | return num * num; 8 | }; 9 | 10 | //impure code 11 | //not so easy... how is num set? Where? 12 | var num = 2; 13 | const squareItImpurely = () => { 14 | //changing num is a side effect 15 | return num * num; 16 | }; 17 | 18 | const saveItem = (item) => { 19 | //working with a DB is a "necessary side effect" 20 | return db.saveItem(item); 21 | } 22 | -------------------------------------------------------------------------------- /Season1/normalizing/04_third_nf.sql: -------------------------------------------------------------------------------- 1 | --3 NF: Non-keys describe the primary key and nothing else 2 | alter table customers drop column if exists id; 3 | alter table films drop column if exists id; 4 | alter table rentals drop column if exists id; 5 | alter table rentals drop column if exists customer_id; 6 | alter table rentals drop column if exists film_id; 7 | 8 | alter table customers add column id serial primary key not null; 9 | alter table films add column id serial primary key not null; 10 | alter table rentals add column id serial primary key not null; 11 | alter table rentals add column customer_id int; 12 | alter table rentals add column film_id int; 13 | -------------------------------------------------------------------------------- /Season2/03-negation/subtraction-bitwise.js: -------------------------------------------------------------------------------- 1 | const add = function (x, y) { 2 | //Iterate till there is no carry 3 | let should_carry = null; 4 | while(should_carry !== 0){ 5 | should_carry = x & y; 6 | x = x ^ y; 7 | y = should_carry << 1 8 | } 9 | return x; 10 | } 11 | 12 | //there are other ways to do this using bitshifting and whatnot 13 | //this, however, is a nice reuse of our existing code to 14 | //drive home the point of ones and twos complement 15 | const subtract = function(x,y){ 16 | if(y === 0) return x; 17 | const ones = ~y; //(~y + 1) - x; 18 | const twos = add(ones,1); 19 | return add(x,twos) 20 | } 21 | 22 | console.log(subtract(27,15)) -------------------------------------------------------------------------------- /Season1/make/web/Makefile: -------------------------------------------------------------------------------- 1 | #goal: replace grunt/gulp/whatever 2 | SASS=node_modules/.bin/node-sass 3 | SASS_FILES=assets/sass/main.scss 4 | JS_FILES=assets/js/*.js 5 | UGLIFY=node_modules/.bin/uglifyjs 6 | DIST_CSS=public/css 7 | DIST_JS=public/js 8 | BUILD_CSS=$(DIST_CSS)/app.css 9 | BUILD_JS=$(DIST_JS)/app.js 10 | 11 | all: $(BUILD_CSS) $(BUILD_JS) 12 | 13 | $(BUILD_CSS): $(DIST_CSS) 14 | @ $(SASS) --output-style compressed $(SASS_FILES) > $@ 15 | 16 | $(BUILD_JS): $(DIST_JS) 17 | @ cat $(JS_FILES) | $(UGLIFY) > $@ 18 | 19 | $(DIST_CSS): 20 | @ mkdir $@ 21 | 22 | $(DIST_JS): 23 | @ mkdir $@ 24 | 25 | clean: 26 | @ rm -rf $(DIST_CSS) $(DIST_JS) 27 | 28 | .PHONY: clean 29 | -------------------------------------------------------------------------------- /Season2/07-encryption/test/one_time_pads.js: -------------------------------------------------------------------------------- 1 | const Spy = require("../lib/spy"); 2 | const OneTimePad = require("../ciphers/onetimepad"); 3 | const assert = require("assert"); 4 | 5 | describe("One time pads", () => { 6 | before(function(){ 7 | const chosenCipher = new OneTimePad(1); 8 | bob = new Spy({cipher: chosenCipher}); 9 | alice = new Spy({cipher: chosenCipher}); 10 | message = "YOU WANT A TOE?"; 11 | bob.send(message, alice); 12 | }); 13 | it("will encrypt", () => { 14 | assert.strictEqual("ZVKMLPZIIZGYCUV", bob.sentMessage) 15 | 16 | }); 17 | it("will decrypt", () => { 18 | assert.strictEqual(message, alice.receivedMessage) 19 | }); 20 | }); -------------------------------------------------------------------------------- /Season1/patterns/creational/method_chaining.js: -------------------------------------------------------------------------------- 1 | //Method Chaining: also known as "fluent interface", 2 | //it can make your code a bit more readable 3 | class ShoppingCart{}; 4 | class ShoppingCartBuilder{ 5 | constructor(){ 6 | this.cart = new ShoppingCart(); 7 | }; 8 | setCreationDate(date){ 9 | this.cart.createdAt = date; 10 | return this; 11 | }; 12 | setItems(items){ 13 | this.cart.items = items; 14 | return this; 15 | }; 16 | build(){ 17 | return this.cart; 18 | }; 19 | }; 20 | var cart = new ShoppingCartBuilder() 21 | .setCreationDate(new Date()) 22 | .setItems([]) 23 | .build(); 24 | console.log(cart); 25 | -------------------------------------------------------------------------------- /Season1/design_principles/solid/interface_seg.cs: -------------------------------------------------------------------------------- 1 | public interface IRegisterable 2 | { 3 | string Name { get; set; } 4 | string Email { get; set; } 5 | string Status { get; set; } 6 | } 7 | public class User : IRegisterable 8 | { 9 | public string Name { get; set; } 10 | public string Email { get; set; } 11 | public string Status { get; set; } 12 | public User () 13 | { 14 | this.Name = "Guest"; 15 | this.Status = "Anonymous"; 16 | } 17 | } 18 | public class Membership 19 | { 20 | public IRegisterable Register (IRegisterable user) 21 | { 22 | //validations etc 23 | user.Status = "Registered"; 24 | //save to the DB or something else 25 | return user; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Season2/04-entropy/shannon.js: -------------------------------------------------------------------------------- 1 | 2 | const lp = { 3 | E: .1202, 4 | T: .0910, 5 | A: .0812, 6 | O: .0768, 7 | I: .0731, 8 | N: .0695, 9 | S: .0628, 10 | R: .0602, 11 | H: .0592, 12 | D: .0432, 13 | L: .0398, 14 | U: .0288, 15 | C: .0271, 16 | M: .0261, 17 | F: .0230, 18 | Y: .0211, 19 | W: .0209, 20 | G: .0203, 21 | P: .0182, 22 | B: .0149, 23 | V: .0111, 24 | K: .0069, 25 | X: .0017, 26 | Q: .0011, 27 | J: .0010, 28 | Z: .0007 29 | }; 30 | 31 | const surprise = (m) => { 32 | const chars = m.split(''); 33 | const probs = chars.map(c => lp[c.toUpperCase()]) 34 | console.log(probs); 35 | return probs.reduce((a,b) => a * b) 36 | } 37 | 38 | console.log(surprise("Hello")); -------------------------------------------------------------------------------- /Season1/design_principles/coupling.js: -------------------------------------------------------------------------------- 1 | //example of two tightly-coupled classes 2 | //User can't exist without Membership 3 | //Membership can't exist without User 4 | //changes to one mean changes to the other 5 | class User{ 6 | constructor(args){ 7 | this.first = args.first; 8 | this.last = args.last; 9 | this.email = args.email; 10 | }; 11 | signIn(login,password){ 12 | //high coupling!!! 13 | return Membership.signInWithLoginPass(login,password); 14 | } 15 | }; 16 | 17 | class Membership{ 18 | signInWithLoginPass(login,password){ 19 | //look up in the db... pretend we found them... 20 | const found = {first: "Joe", last: "Bob", email: "test@test.com"}; 21 | return new User(found); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /Season1/design_principles/solid/basis.js: -------------------------------------------------------------------------------- 1 | //Single reason to change 2 | class User{ 3 | constructor(args){ 4 | this.first = args.first; 5 | this.last = args.last; 6 | this.email = args.email; 7 | }; 8 | } 9 | class Membership{ 10 | register(args){ 11 | // 12 | } 13 | } 14 | 15 | //Open/Closed principle 16 | //open for extension, closed for modification 17 | class RobsMembership extends Membership{ 18 | //do what I want to 19 | } 20 | 21 | //Liskov Substitution 22 | class Administrator extends User{ 23 | //I should be able to pass this instance 24 | //as if it were a User... or an Administrator type 25 | } 26 | 27 | //Interface Segregation 28 | //see the C# example 29 | 30 | //Dependency Inversion 31 | //see tghe C# example 32 | -------------------------------------------------------------------------------- /Season1/scripts/jekyll_post.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # a Jekyll post creator, which creates a new file, adds frontmatter, 3 | # and opens the editor and starts Jekyll 4 | new_post() { 5 | JEKYLL_ROOT=~/Documents/Sites/conery-io-jekyll 6 | JEKYLL_POSTS=$JEKYLL_ROOT/_posts 7 | TITLE=$1 8 | SLUGIFIED="$(echo -n "$TITLE" | sed -e 's/[^[:alnum:]]/-/g' | tr -s '-' | tr A-Z a-z)" 9 | NEW_POST_FILE=$JEKYLL_POSTS/$(date +%Y-%m-%d-$SLUGIFIED.md) 10 | 11 | cat < $NEW_POST_FILE 12 | --- 13 | layout: post-minimal 14 | title: "$TITLE" 15 | image: '' 16 | comments: false 17 | categories: 18 | summary: "" 19 | --- 20 | frontmatter 21 | 22 | echo "New post created, opening in Atom, starting Jekyll" 23 | atom $NEW_POST_FILE 24 | jekyll serve -s $JEKYLL_ROOT 25 | } 26 | -------------------------------------------------------------------------------- /Season1/design_principles/cohesion.js: -------------------------------------------------------------------------------- 1 | //A nicely cohesive set of classes and objects 2 | //They exist independently, but have a "cohesive" 3 | //notion of what they do. A User describes a User, 4 | //Membership does membership stuff, etc. 5 | const UserRepo = { 6 | get : function(id){ 7 | //look up in the DB or something 8 | const found = db.findUser(id); 9 | return new User(found); 10 | } 11 | } 12 | class User{ 13 | constructor(args){ 14 | this.first = args.first; 15 | this.last = args.last; 16 | this.email = args.email; 17 | }; 18 | }; 19 | class Membership{ 20 | signInWithLoginPass(login,password){ 21 | //look up in the db... pretend we found them... 22 | const found = 123; 23 | return {authenticated: true, id: 123}; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /Season2/07-encryption/ciphers/alphabet.js: -------------------------------------------------------------------------------- 1 | 2 | class Alphabet { 3 | constructor(){ 4 | this.chars = [ 5 | "A", "B", "C", "D", 6 | "E", "F", "G", "H", 7 | "I", "J", "K", "L", 8 | "M", "N", "O", "P", 9 | "Q", "R", "S", "T", 10 | "U", "V", "W", "X", 11 | "Y", "Z", " ", "?", "!" 12 | ]; 13 | } 14 | getOffsetChar({char, offsetChar, encrypting=true}){ 15 | const charPosition = this.chars.indexOf(char); 16 | const keyPosition = this.chars.indexOf(offsetChar); 17 | const offsetPosition = encrypting ? (charPosition + keyPosition) : (charPosition - keyPosition); 18 | let idx = (offsetPosition) % this.chars.length; 19 | if(offsetPosition < 0 ) idx = this.chars.length - -idx; 20 | return this.chars[idx] 21 | } 22 | 23 | } 24 | module.exports = new Alphabet(); -------------------------------------------------------------------------------- /Season1/algorithms/simple/merge_sort.js: -------------------------------------------------------------------------------- 1 | const list = [23,4,42,15,16,8,3]; 2 | const mergeSort = (list) => { 3 | if(list.length <= 1) return list; 4 | const middle = list.length/2; 5 | const left = list.slice(0,middle); 6 | const right = list.slice(middle,list.length); 7 | return merge(mergeSort(left), mergeSort(right)); 8 | } 9 | const merge = (left, right) => { 10 | var result = []; 11 | while(left.length || right.length){ 12 | if(left.length && right.length){ 13 | if(left[0] < right[0]){ 14 | result.push(left.shift()); 15 | }else{ 16 | result.push(right.shift()); 17 | } 18 | }else if(left.length){ 19 | result.push(left.shift()); 20 | }else{ 21 | result.push(right.shift()); 22 | } 23 | } 24 | return result; 25 | } 26 | 27 | console.log(mergeSort(list)); 28 | -------------------------------------------------------------------------------- /Season2/062-error-correction/index.js: -------------------------------------------------------------------------------- 1 | const Encoder = require("./encoder"); 2 | 3 | const message = `You want a toe? I can get you a toe, believe me. There are ways, Dude. You don't wanna know about it, believe me.` 4 | 5 | const flipABit = function(message,n){ 6 | const binaryMessage = message.split(""); 7 | console.log("Flipping at",n); 8 | binaryMessage[n] = binaryMessage[n] === "1" ? "0" : "1"; 9 | return binaryMessage.join("") 10 | } 11 | 12 | const encoder = new Encoder(); 13 | const encoded = encoder.encode(message); 14 | ///ZZZIIIIPPPPP! COSMIC RAY... 15 | let erroredMessage = flipABit(encoded,58); 16 | erroredMessage = flipABit(erroredMessage,72); 17 | const decoded = encoder.decode(erroredMessage); 18 | //output so we an replace 19 | console.log(encoded); 20 | console.log(decoded); 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Season2/07-encryption/ciphers/onetimepad.js: -------------------------------------------------------------------------------- 1 | const alphabet = require("./alphabet"); 2 | const pads = require("../data/pads"); 3 | 4 | const offsets = function(text, pad, encrypting=true){ 5 | const out = [], chars=text.split(""), keys=pad.split(""); 6 | for(let i=0; i < text.length; i++){ 7 | const offsetChar = alphabet.getOffsetChar({char: chars[i], offsetChar: keys[i], encrypting: encrypting}) 8 | out.push(offsetChar) 9 | } 10 | return out.join(""); 11 | } 12 | 13 | class OneTimePad{ 14 | constructor(padNumber){ 15 | this.pad = pads[padNumber]; 16 | this.alphabetLength = alphabet.length; 17 | } 18 | encrypt(plainText){ 19 | return offsets(plainText,this.pad,true); 20 | } 21 | decrypt(cipherText){ 22 | return offsets(cipherText,this.pad,false); 23 | } 24 | } 25 | module.exports = OneTimePad; 26 | -------------------------------------------------------------------------------- /Season1/patterns/structural/flyweight.js: -------------------------------------------------------------------------------- 1 | //Flyweight: small, immutable objects for larger systems 2 | class Table{ 3 | constructor(args){ 4 | return Object.freeze(args); 5 | }; 6 | }; 7 | const TableFactory = function(){ 8 | const factory = {}; 9 | //a db call, or do it by hand... 10 | factory.tables = [ 11 | new Table({name: "customers", pk: "id"}), 12 | new Table({name: "orders", pk: "id"}), 13 | new Table({name: "order_items", pk: "id"}) 14 | ]; 15 | factory.getTable = (name) => { 16 | return factory.tables.find(t => t.name === name); 17 | }; 18 | return factory; 19 | }(); 20 | class PgAdapter{ 21 | constructor(connectionString){ 22 | this.connectionString = connectionString; 23 | this.name = "Postgres Adapter"; 24 | this.tables = TableFactory; 25 | }; 26 | //... 27 | } 28 | const adapter = new PgAdapter("test"); 29 | console.log(adapter); 30 | -------------------------------------------------------------------------------- /Season2/07-encryption/lib/bad_guy.js: -------------------------------------------------------------------------------- 1 | const dictionary = require("../data/dictionary.json"); 2 | const Caesar = require("../ciphers/caeser"); 3 | 4 | class BadGuy { 5 | constructor(){ 6 | this.cipher = new Caesar(); 7 | } 8 | crack(encryptedMessage){ 9 | let wordScore = 0, offset=1; 10 | while (offset < 10000000) { //keep our loop from going too long 11 | this.cipher.offset = offset; 12 | const candidate = this.cipher.decrypt(encryptedMessage); 13 | const possibleWords = candidate.split(" "); 14 | if(possibleWords.length > 0){ 15 | for(let word of possibleWords){ 16 | if(dictionary[word.toLowerCase()] > -1){ 17 | wordScore+=1; 18 | if(wordScore > 2) return candidate; 19 | } 20 | } 21 | } 22 | offset+=1; 23 | } 24 | return "I'm STUMPED" 25 | } 26 | } 27 | 28 | module.exports = BadGuy; -------------------------------------------------------------------------------- /Season1/patterns/creational/singleton.cs: -------------------------------------------------------------------------------- 1 | //from Jon Skeet: http://csharpindepth.com/Articles/General/Singleton.aspx 2 | //Thread safe, not quite lazy 3 | public sealed class Singleton 4 | { 5 | private static readonly Singleton instance = new Singleton(); 6 | 7 | // Explicit static constructor to tell C# compiler 8 | // not to mark type as beforefieldinit 9 | static Singleton() 10 | { 11 | } 12 | 13 | private Singleton() 14 | { 15 | } 16 | 17 | public static Singleton Instance 18 | { 19 | get 20 | { 21 | return instance; 22 | } 23 | } 24 | } 25 | 26 | public sealed class LazySingleton 27 | { 28 | private static readonly Lazy lazy = 29 | new Lazy(() => new Singleton()); 30 | 31 | public static Singleton Instance { get { return lazy.Value; } } 32 | 33 | private Singleton() 34 | { 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Season2/07-encryption/test/diffie_helman.js: -------------------------------------------------------------------------------- 1 | const DiffieHellman = require("../ciphers/dhm"); 2 | const assert = require("assert"); 3 | 4 | describe("Diffie-Hellman-Merkel Key Exchange", () => { 5 | let alice,bob; 6 | before(function(){ 7 | bob = new DiffieHellman({generator: 5, secret: 4, modulus: 9}); 8 | alice = new DiffieHellman({generator: 5, secret: 2, modulus: 9}); 9 | }); 10 | 11 | it("alice's public key is 7", () => { 12 | assert.strictEqual(alice.publicKey, 7); 13 | }); 14 | it("bob's public key is 4", () => { 15 | assert.strictEqual(bob.publicKey, 4); 16 | }); 17 | it("alice's encryption key is 7", () => { 18 | assert.strictEqual(alice.encryptionKey(bob.publicKey), 7); 19 | }); 20 | it("alice's encryption key is 7", () => { 21 | assert.strictEqual(bob.encryptionKey(alice.publicKey), 7); 22 | }); 23 | it("eve is completely stumped", () => { 24 | assert(true) 25 | }); 26 | }); -------------------------------------------------------------------------------- /Season1/design_principles/dependency_injection.js: -------------------------------------------------------------------------------- 1 | const UserRepo = { 2 | get : function(id){ 3 | //look up in the DB or something 4 | const found = db.findUser(id); 5 | return new User(found); 6 | }, 7 | save: function(user){ 8 | //put back to DB 9 | } 10 | } 11 | class User{ 12 | constructor(args){ 13 | this.first = args.first; 14 | this.last = args.last; 15 | this.email = args.email; 16 | }; 17 | }; 18 | 19 | class Membership{ 20 | constructor(args){ 21 | this.repo = args.repo; 22 | }; 23 | signInWithLoginPass(login,password){ 24 | //look up in the db... pretend we found them... 25 | const found = 123; 26 | return {authenticated: true, id: 123}; 27 | }; 28 | //a better choice to avoid LOD problems 29 | suspendUser(id){ 30 | var user = this.repo.get(id); 31 | user.status = "suspended"; 32 | this.repo.save(user); 33 | } 34 | }; 35 | const membership = new Membership({repo: UserRepo}) 36 | -------------------------------------------------------------------------------- /Season1/patterns/behavioral/observer.js: -------------------------------------------------------------------------------- 1 | //Observer: event-based programming 2 | class Observable{ 3 | constructor(){ 4 | this.listeners = []; 5 | } 6 | listen(eventName, fn){ 7 | this.listeners.push({eventName: eventName, fn: fn}); 8 | }; 9 | notify(eventName, data){ 10 | //get the listeners for a given event 11 | const listeners = this.listeners.filter(x => x.eventName === eventName); 12 | for(var listener of listeners) listener.fn(data); 13 | }; 14 | } 15 | class ShoppingCart extends Observable{ 16 | constructor(key){ 17 | super(); 18 | this.key = key; 19 | this.items = []; 20 | this.createdAt = new Date(); 21 | }; 22 | 23 | addItem(item){ 24 | this.items.push(item); 25 | this.notify("item-added",this); 26 | }; 27 | }; 28 | //wire the ShoppingCart for events 29 | const cart = new ShoppingCart("test"); 30 | cart.listen("item-added", cart => { 31 | console.log(cart); 32 | }); 33 | cart.addItem({sku: "BOOTS"}); 34 | -------------------------------------------------------------------------------- /Season2/08-hashes/hashes.js: -------------------------------------------------------------------------------- 1 | const crypto = require("crypto"); 2 | 3 | const hash = crypto.createHash("sha256") 4 | .update("hi") 5 | .digest("latin1"); 6 | console.log(hash); 7 | 8 | //008c70392e3abfbd0fa47bbc2ed96aa99bd49e159727fcba0f2e6abeb3a9d601 9 | 10 | 11 | const bcrypt = require('bcryptjs'); 12 | const salt = bcrypt.genSaltSync(10); 13 | let hash = bcrypt.hashSync("Password123", salt); 14 | 15 | 16 | 17 | const hashPassword = function(pw){ 18 | return new Promise(function(resolve, reject){ 19 | crypto.scrypt(pw,"nubbins",32, {cost: 2**14}, function(err, buffer){ 20 | if(err) reject(err); 21 | else resolve(buffer.toString("hex")) 22 | }); 23 | }) 24 | } 25 | //4396dac13f570e079b82fb27bfe2b734ec693ad7817ad6f618fc6d8f738bc02d 26 | 27 | const go = async function(){ 28 | const hash = await hashPassword("Password123"); 29 | return hash; 30 | } 31 | 32 | go().then(console.log) 33 | 34 | 35 | //4d1dcbdb6ea1057544181950b25ab8ddfd3d8045b4a1407c5d4555da2cf2798d -------------------------------------------------------------------------------- /Season2/05-encoding/lovebug.js: -------------------------------------------------------------------------------- 1 | class LoveBug { 2 | constructor() { 3 | this.messages = { 4 | "!" : "000", 5 | "G" : "001", 6 | "O" : "010", 7 | "F" : "011", 8 | "M" : "100", 9 | "🙄" : "101", 10 | "💩" : "110", 11 | " " : "111" 12 | }; 13 | this.chars = this.messages.length; 14 | } 15 | 16 | encode(message){ 17 | let out = []; 18 | for(let c of message){ 19 | if(!this.messages[c]) throw new Error("Don't know how to encode that"); 20 | out.push(this.messages[c]); 21 | } 22 | return out.join(""); 23 | } 24 | 25 | decode(message){ 26 | let out = []; 27 | for(let i = 0; i < message.length; i+=3){ 28 | const thisBlock = message.substring(i, i+3); 29 | const key = Object.keys(this.messages).find(k => this.messages[k] === thisBlock) 30 | out.push(key); 31 | } 32 | return out.join(""); 33 | } 34 | 35 | 36 | } 37 | 38 | 39 | 40 | module.exports = LoveBug; 41 | -------------------------------------------------------------------------------- /Season1/patterns/behavioral/command.js: -------------------------------------------------------------------------------- 1 | //Command: formalize a request from one API to another 2 | class ShoppingCart{ 3 | constructor(key){ 4 | this.key = key; 5 | this.items = []; 6 | this.createdAt = new Date(); 7 | }; 8 | addItem(item){ 9 | this.items.push(item); 10 | }; 11 | }; 12 | const assert = require("assert"); 13 | class SaveCartCommand{ 14 | constructor(cart){ 15 | assert(cart, "A cart is required"); 16 | //prepare the command 17 | this.sql = "insert into shopping_carts(key, body) values($1, $2);"; 18 | this.params = [cart.key, JSON.stringify(cart)]; 19 | }; 20 | execute(){ 21 | //use the SQL and params to send to the DB 22 | //transactions FTW! 23 | //logging, all kinds of fun things 24 | console.log(this.sql); 25 | console.log(this.params); 26 | console.log("Saved!"); 27 | }; 28 | }; 29 | const cart = new ShoppingCart("Test"); 30 | cart.addItem({sku: "socks"}); 31 | const cmd = new SaveCartCommand(cart); 32 | cmd.execute(); 33 | -------------------------------------------------------------------------------- /Season1/normalizing/03_second_nf.sql: -------------------------------------------------------------------------------- 1 | --2 NF: Must be in 1NF and each row must be identifiable by a unique value or set of values, aka a "primary key" 2 | drop table if exists customers; 3 | drop table if exists rentals; 4 | drop table if exists films; 5 | create table customers( 6 | email varchar(255), 7 | name varchar(255) 8 | ); 9 | insert into customers(email, name) 10 | select email, customer from rental_first_nf group by email, customer; 11 | create table rentals( 12 | email varchar(255), 13 | film_title varchar(50), 14 | number varchar(50), 15 | date date, 16 | total money 17 | ); 18 | insert into rentals(email, film_title, number, date, total) 19 | select email, title, rental_number, rental_date, total 20 | from rental_first_nf 21 | group by email, title, rental_number, rental_date, total; 22 | create table films( 23 | title varchar(50), 24 | rating varchar(50), 25 | fee money 26 | ); 27 | insert into films(title, rating, fee) 28 | select title, rating, fee from rental_first_nf group by title, rating, fee; 29 | -------------------------------------------------------------------------------- /Season1/design_principles/tell_dont_ask.js: -------------------------------------------------------------------------------- 1 | //this class is set up so that we have to ask 2 | //far too many questions, knowing too much about 3 | //the internal workings... 4 | class GroovyQuery{ 5 | isCommandValid(){ 6 | //do something 7 | }; 8 | isConnectionAvailable(){ 9 | //check conn pool to see if 10 | //one is free 11 | }; 12 | execute(sql){ 13 | //run it 14 | }; 15 | } 16 | const query = new Query(); 17 | //Bleh! We're asking too many questions... 18 | if(query.isCommandValid("select * from") && query.isConnectionAvailable()){ 19 | query.execute(); 20 | }; 21 | 22 | //Tell it what to do! Have it tell YOU when things 23 | //aren't the way they should be... 24 | class GroovyQuery2{ 25 | execute(cmd){ 26 | //check if it's valid 27 | isValid = (cmd) =>{ 28 | //... 29 | }; 30 | //see if there's a connection 31 | haveConnection = () => { 32 | //... 33 | } 34 | if(isValid(cmd) && haveConnection()){ 35 | //run 36 | }else{ 37 | //return an error 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Season1/design_principles/law_of_demeter.js: -------------------------------------------------------------------------------- 1 | const UserRepo = { 2 | get : function(id){ 3 | //look up in the DB or something 4 | const found = db.findUser(id); 5 | return new User(found); 6 | }, 7 | save: function(user){ 8 | //put back to DB 9 | } 10 | } 11 | class User{ 12 | constructor(args){ 13 | this.first = args.first; 14 | this.last = args.last; 15 | this.email = args.email; 16 | }; 17 | // suspend(){ 18 | // this.status = "suspended"; 19 | // UserRepo.save(this); 20 | // } 21 | }; 22 | 23 | //reaching through one class to get to another 24 | //to do some kind of operation 25 | //UserRepo.get(1).suspend(); 26 | 27 | class Membership{ 28 | signInWithLoginPass(login,password){ 29 | //look up in the db... pretend we found them... 30 | const found = 123; 31 | return {authenticated: true, id: 123}; 32 | }; 33 | //a better choice to avoid LOD problems 34 | suspendUser(id){ 35 | var user = UserRepo.get(id); 36 | user.status = "suspended"; 37 | UserRepo.save(user); 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /Season1/patterns/structural/facade.js: -------------------------------------------------------------------------------- 1 | //Facade: Hides implementation details and makes choices for calling code 2 | class PgAdapter{ 3 | constructor(connectionString){ 4 | this.connectionString = connectionString; 5 | this.name = "Postgres Adapter" 6 | }; 7 | save(item){ 8 | console.log("Saving to PG"); 9 | }; 10 | } 11 | class RedisAdapter{ 12 | constructor(connectionString){ 13 | this.connectionString = connectionString; 14 | this.name = "Redis Adapter" 15 | }; 16 | save(item){ 17 | console.log("Saving to Redis"); 18 | }; 19 | } 20 | //this can be a function or a class or whatever... 21 | const AdapterFacade = function(connectionString) { 22 | if(connectionString.startsWith("postgres")){ 23 | return new PgAdapter(connectionString); 24 | }else if(connectionString.startsWith("redis")){ 25 | return new RedisAdapter(connectionString); 26 | }else{ 27 | throw new Exception("That connection isn't supported"); 28 | } 29 | }; 30 | 31 | //export as a module to hide the implementation 32 | module.exports = AdapterFacade; 33 | -------------------------------------------------------------------------------- /Season1/patterns/structural/lib/poolable.js: -------------------------------------------------------------------------------- 1 | class Connection{ 2 | constructor(connectionString){ 3 | this.connectionString = connectionString; 4 | this.close(); 5 | }; 6 | open(){ 7 | this.checkedOut = true; 8 | this.status = "open"; 9 | }; 10 | close(){ 11 | this.checkedOut = false; 12 | this.status = "closed"; 13 | } 14 | }; 15 | class ConnectionPool{ 16 | constructor(connectionString, poolSize = 10){ 17 | this.pool = []; 18 | for (var i = 0; i < 10; i++) { 19 | const conn = new Connection(connectionString); 20 | this.pool.push(conn); 21 | } 22 | }; 23 | checkout(){ 24 | const found = this.pool.find(c => c.checkedOut === false); 25 | if(found){ 26 | found.open(); 27 | return found; 28 | }else{ 29 | throw new Exception("No available connections"); 30 | } 31 | }; 32 | checkin(conn){ 33 | conn.close(); 34 | }; 35 | drain(){ 36 | for(var conn of this.pool){ 37 | conn.close(); 38 | } 39 | }; 40 | }; 41 | 42 | module.exports = (adapter, poolSize = 10) => { 43 | adapter.pool = new ConnectionPool(adapter.connectionString, poolSize); 44 | return adapter; 45 | } 46 | -------------------------------------------------------------------------------- /Season2/07-encryption/test/simple_encryption.js: -------------------------------------------------------------------------------- 1 | const Spy = require("../lib/spy"); 2 | const Caesar = require("../ciphers/caeser"); 3 | const BadGuy = require("../lib/bad_guy"); 4 | const assert = require("assert"); 5 | 6 | describe("Caesar ciphers", () => { 7 | let bob, message, alice=null; 8 | before(async function(){ 9 | const chosenCipher = new Caesar(1); 10 | bob = new Spy({cipher: chosenCipher}); 11 | alice = new Spy({cipher: chosenCipher}); 12 | message = "You want a toe? I can get you a toe, believe me. There are ways, Dude. You don't wanna know about it, believe me." 13 | bob.send(message, alice); 14 | }); 15 | 16 | it("will encrypt with a simple 1 char offset", () => { 17 | assert.strictEqual(bob.sentMessage, "Zpv!xbou!b!upf@!J!dbo!hfu!zpv!b!upf-!cfmjfwf!nf/!Uifsf!bsf!xbzt-!Evef/!Zpv!epo(u!xboob!lopx!bcpvu!ju-!cfmjfwf!nf/"); 18 | }); 19 | 20 | it("can easily be decrypted", () => { 21 | assert.strictEqual(alice.receivedMessage, message); 22 | }); 23 | 24 | it("can easily be cracked", () => { 25 | const eve = new BadGuy(); 26 | const cracked = eve.crack(bob.sentMessage); 27 | assert.strictEqual(cracked, message); 28 | }); 29 | 30 | }); 31 | -------------------------------------------------------------------------------- /Season1/patterns/behavioral/mediator.js: -------------------------------------------------------------------------------- 1 | //Mediator: a class that sits between two other classes 2 | //to decrease coupling and complexity 3 | class ShoppingCart{ 4 | constructor(key){ 5 | this.key = key; 6 | this.items = []; 7 | this.createdAt = new Date(); 8 | }; 9 | addItem(item){ 10 | this.items.push(item); 11 | }; 12 | }; 13 | //our mediator 14 | class DocumentStore{ 15 | constructor(adapter){ 16 | this.db = adapter; 17 | }; 18 | save(table, item){ 19 | const sql = `insert into ${table}(key, body) values($1, $2)`; 20 | const params = [item.key, JSON.stringify(item)]; 21 | this.db.execute(sql, params); 22 | }; 23 | }; 24 | class PgAdapter{ 25 | execute(sql, params){ 26 | console.log("Executing pg query"); 27 | console.log(sql); 28 | }; 29 | } 30 | const assert = require("assert"); 31 | class SaveCartCommand{ 32 | constructor(cart, adapter){ 33 | assert(cart, "A cart is required"); 34 | this.store = new DocumentStore(adapter); 35 | this.cart = cart; 36 | }; 37 | execute(){ 38 | this.store.save("shopping_carts", cart); 39 | }; 40 | }; 41 | const cart = new ShoppingCart("Test"); 42 | cart.addItem({sku: "socks"}); 43 | const cmd = new SaveCartCommand(cart, new PgAdapter()); 44 | cmd.execute(); 45 | -------------------------------------------------------------------------------- /Season1/algorithms/dynamic_programming/bellman-ford.js: -------------------------------------------------------------------------------- 1 | //Bellman-Ford: Shortest path calculation 2 | //on an edge-weighted, directed graph 3 | const vertices = ["S", "A", "B", "C", "D", "E"]; 4 | var memo = { 5 | S:0, 6 | A:Number.POSITIVE_INFINITY, 7 | B:Number.POSITIVE_INFINITY, 8 | C:Number.POSITIVE_INFINITY, 9 | D:Number.POSITIVE_INFINITY, 10 | E:Number.POSITIVE_INFINITY 11 | }; 12 | const graph = [ 13 | {from : "S", to : "A", cost: 4}, 14 | {from : "S", to :"E", cost: -5}, 15 | {from : "A", to :"C", cost: 6}, 16 | {from : "B", to :"A", cost: 3}, 17 | {from : "C", to :"B", cost: -2}, 18 | {from : "D", to :"C", cost: 3}, 19 | {from : "D", to :"A", cost: 10}, 20 | {from : "E", to: "D", cost: 8} 21 | ]; 22 | 23 | const iterate = () => { 24 | var doItAgain = false; 25 | for(fromVertex of vertices){ 26 | const edges = graph.filter(path => { 27 | return path.from === fromVertex; 28 | }); 29 | for(edge of edges){ 30 | const potentialCost = memo[edge.from] + edge.cost; 31 | if(potentialCost < memo[edge.to]){ 32 | memo[edge.to] = potentialCost; 33 | doItAgain = true; 34 | } 35 | } 36 | } 37 | return doItAgain; 38 | } 39 | for(vertex of vertices){ 40 | if(!iterate()) break; 41 | } 42 | console.log(memo); 43 | -------------------------------------------------------------------------------- /Season1/functional/immutability.exs: -------------------------------------------------------------------------------- 1 | #Immutability 2 | defmodule Friend do 3 | defstruct name: "", age: 0 4 | end 5 | 6 | defmodule Immutability do 7 | def change_name(friend, new_name) do 8 | Map.put(friend, :name, new_name) 9 | end 10 | def get_friend do 11 | %Friend{name: "Jon"} 12 | end 13 | end 14 | friend = %{name: "Clara"} 15 | friend = Map.put(friend, :name, "Mike") 16 | IO.inspect friend 17 | 18 | Immutability.get_friend |> Immutability.change_name("Jolene") |> IO.inspect 19 | 20 | 21 | #Idiomatic Elixir 22 | defmodule Cart do 23 | defstruct items: [], total: 0, count: 0 24 | end 25 | 26 | defmodule Shopping do 27 | def add_item(%Cart{} = cart, %{sku: _, price: price} = item) do 28 | %{cart | items: cart.items ++ [item], total: cart.total + price, count: cart.count + 1} 29 | end 30 | def get_cart, do: %Cart{} 31 | def save_cart(cart), do: cart 32 | end 33 | 34 | Shopping.get_cart 35 | |> Shopping.add_item(%{sku: "SOCKS", price: 12.22}) 36 | |> IO.inspect 37 | 38 | 39 | defmodule Ops do 40 | def square_it(n), do: n * n 41 | def double_it(n), do: n + n 42 | def root_it(n), do: :math.sqrt n 43 | def print_it(n), do: IO.inspect n 44 | end 45 | 46 | # Transforming data 47 | 4 |> Ops.square_it 48 | |> Ops.double_it 49 | |> Ops.root_it 50 | |> Ops.print_it 51 | -------------------------------------------------------------------------------- /Season1/patterns/behavioral/state.js: -------------------------------------------------------------------------------- 1 | //State: formalizing object status into a class 2 | class ShoppingCart{ 3 | constructor(key){ 4 | this.key = key; 5 | this.state = new NewCartStatus(this); 6 | this.items = []; 7 | this.errors = []; 8 | //... 9 | }; 10 | addItem(item){ 11 | this.state.addItem(item); 12 | }; 13 | removeItem(item){ 14 | this.state.removeItem(item); 15 | } 16 | setCheckedOut(){ 17 | //transition the state of the object 18 | //affecting it's behavior 19 | this.state = new CheckedOutCartStatus(this); 20 | } 21 | }; 22 | class NewCartStatus{ 23 | //cart is new, can do anything to it! 24 | constructor(cart){ 25 | this.cart = cart; 26 | }; 27 | addItem(item){ 28 | this.cart.items.push(item); 29 | }; 30 | removeItem(item){ 31 | this.cart.items.splice(this.items.indexOf(item, 1)); 32 | }; 33 | }; 34 | class CheckedOutCartStatus{ 35 | //cart is new, can do anything to it! 36 | constructor(cart){ 37 | this.cart = cart; 38 | }; 39 | addItem(item){ 40 | this.cart.errors.push("Can't add an item to a cart that's checked out"); 41 | }; 42 | removeItem(item){ 43 | this.cart.errors.push("Can't remove an item to a cart that's checked out"); 44 | }; 45 | }; 46 | const cart = new ShoppingCart("test"); 47 | cart.setCheckedOut(); 48 | cart.addItem({sku: "soup"}); 49 | console.log(cart); 50 | -------------------------------------------------------------------------------- /Season2/06-error-correction/index.js: -------------------------------------------------------------------------------- 1 | const Encoder = require("./encoder"); 2 | 3 | const message = `You want a toe? I can get you a toe, believe me. There are ways, Dude. You don't wanna know about it, believe me.` 4 | // const encodedWithErrors = `110000111010100110101011000000011011001111010000001101010011011100010011010010001101000010000000110111010001100010010011110101100001110101001101000000110101001101110001001101000001001000101101000001001010100100110100110000100110101001100111001001000100100110100000010001001001101010110000001100010010110100001110100000110010011010110000111010100110100001101110011011001111010101100000001101011010000011010010100110101110101101101000000000010111010100100111101001000100111101000001001000101101000001001010100100110100110000101`; 5 | 6 | 7 | const encodedWithErrors = `010111011110011000001001010001100011000010000000110111101000110100000100000000110000010110101001100001011101111001100001000000011011110100010000010110001110110101011011010000101011010000011110010111100010000100111010100000100101000101111111000001011001100101101000010111011110011000001010111011000110000010010100011001100100000010110010110011100100100001101000000111100110011000110100110001000101011000111011010101101101000010101101`; 8 | 9 | const encoder = new Encoder(); 10 | const encoded = encoder.encode(message); 11 | 12 | 13 | 14 | //output so we an replace 15 | console.log(encoded); 16 | console.log(encoder.decode(encodedWithErrors)); 17 | -------------------------------------------------------------------------------- /Season1/design_principles/solid/dependency_inversion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace DI 3 | { 4 | public interface IMembershipStore 5 | { 6 | void Save (object item); 7 | } 8 | 9 | public class PostgreSQLAdapter : IMembershipStore 10 | { 11 | public void Save (object item) 12 | { 13 | //database call... 14 | } 15 | } 16 | public interface IRegisterable 17 | { 18 | string Name { get; set; } 19 | string Email { get; set; } 20 | string Status { get; set; } 21 | } 22 | public class User : IRegisterable 23 | { 24 | public string Name { get; set; } 25 | public string Email { get; set; } 26 | public string Status { get; set; } 27 | public User () 28 | { 29 | this.Name = "Guest"; 30 | this.Status = "Anonymous"; 31 | } 32 | } 33 | public class Membership 34 | { 35 | IMembershipStore _store; 36 | //dependency inversion is the STYLE we're using 37 | //although it looks the same as Dependency Injection 38 | //we're simply making sure we depend on a low-level 39 | //implementation, rather than a high-level one 40 | //such as PostgreSQLAdapter 41 | public Membership (IMembershipStore store) 42 | { 43 | _store = store; 44 | } 45 | public IRegisterable Register (IRegisterable user) 46 | { 47 | //validations etc 48 | user.Status = "Registered"; 49 | _store.Save (user); 50 | return user; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Season1/patterns/behavioral/strategy.js: -------------------------------------------------------------------------------- 1 | //Strategy: formalizing an orchestration of patterns 2 | const assert = require("assert"); 3 | class ShoppingCart{ 4 | constructor(key){ 5 | this.key = key; 6 | this.items = []; 7 | this.createdAt = new Date(); 8 | }; 9 | addItem(item){ 10 | this.items.push(item); 11 | }; 12 | }; 13 | //the strategy 14 | class PgDocumentStorageStrategy{ 15 | constructor(){ 16 | this.store = new DocumentStore(new PgAdapter()); 17 | }; 18 | save(collection, item){ 19 | this.store.save(collection, item); 20 | }; 21 | } 22 | //our mediator 23 | class DocumentStore{ 24 | constructor(adapter){ 25 | this.db = adapter; 26 | }; 27 | save(table, item){ 28 | const sql = `insert into ${table}(key, body) values($1, $2)`; 29 | const params = [item.key, JSON.stringify(item)]; 30 | this.db.execute(sql, params); 31 | }; 32 | }; 33 | class PgAdapter{ 34 | execute(sql, params){ 35 | console.log("Executing pg query"); 36 | console.log(sql); 37 | }; 38 | } 39 | 40 | class SaveCartCommand{ 41 | constructor(cart, storageStrategy){ 42 | assert(cart, "A cart is required"); 43 | this.storageStrategy = storageStrategy; 44 | this.cart = cart; 45 | }; 46 | execute(){ 47 | this.storageStrategy.save("shopping_carts", cart); 48 | }; 49 | }; 50 | const cart = new ShoppingCart("Test"); 51 | cart.addItem({sku: "socks"}); 52 | const cmd = new SaveCartCommand(cart, new PgDocumentStorageStrategy()); 53 | cmd.execute(); 54 | -------------------------------------------------------------------------------- /Season2/05-encoding/encoder.js: -------------------------------------------------------------------------------- 1 | class Encoder{ 2 | 3 | constructor(){ 4 | this.encoding = { 5 | "A" : "0100", 6 | "B" : "100000", 7 | "C" : "001000", 8 | "D" : "00101", // not 00110 9 | "E" : "101", 10 | "F" : "10010", 11 | "G" : "010100", 12 | "H" : "1100", 13 | "I" : "1101", 14 | "J" : "010110000", 15 | "K" : "01011001", 16 | "L" : "10001", 17 | "M" : "010101", 18 | "N" : "0110", 19 | "O" : "0111", 20 | "P" : "100001", 21 | "Q" : "0101100010", 22 | "R" : "1110", 23 | "S" : "1111", 24 | "T" : "0011", 25 | "U" : "10011", 26 | "V" : "0101101", 27 | "W" : "001001", 28 | "X" : "01011000110", 29 | "Y" : "010111", 30 | "Z" : "01011000111", 31 | " " : "000" 32 | } 33 | } 34 | 35 | encode(message){ 36 | const words = message.toUpperCase(), out = []; 37 | for(let char of words){ 38 | const encoding = this.encoding[char]; 39 | //if the character can be encoded great. If not, ignore 40 | if(encoding) out.push(encoding); 41 | } 42 | return out.join(""); 43 | } 44 | 45 | decode(binaryMessage){ 46 | let out = [], codeWord = ""; 47 | for(let bit of binaryMessage){ 48 | codeWord+=bit; 49 | const key = Object.keys(this.encoding).find(k => this.encoding[k] === codeWord); 50 | if(key){ 51 | out.push(key); 52 | codeWord = ""; 53 | } 54 | } 55 | return out.join(""); 56 | } 57 | 58 | } 59 | 60 | module.exports = Encoder; -------------------------------------------------------------------------------- /Season1/patterns/structural/composite.js: -------------------------------------------------------------------------------- 1 | //Composite: parent/child composition providing single-object functionality 2 | //Connection and ConnectionPool are composed to provide a single bit of functionality 3 | class Connection{ 4 | constructor(connectionString){ 5 | this.connectionString = connectionString; 6 | this.close(); 7 | }; 8 | open(){ 9 | this.checkedOut = true; 10 | this.status = "open"; 11 | }; 12 | close(){ 13 | this.checkedOut = false; 14 | this.status = "closed"; 15 | } 16 | }; 17 | class ConnectionPool{ 18 | constructor(connectionString, poolSize = 10){ 19 | this.pool = []; 20 | for (var i = 0; i < 10; i++) { 21 | const conn = new Connection(connectionString); 22 | this.pool.push(conn); 23 | } 24 | }; 25 | checkout(){ 26 | const found = this.pool.find(c => c.checkedOut === false); 27 | if(found){ 28 | found.open(); 29 | return found; 30 | }else{ 31 | throw new Exception("No available connections"); 32 | } 33 | }; 34 | checkin(conn){ 35 | conn.close(); 36 | }; 37 | drain(){ 38 | for(var conn of this.pool){ 39 | conn.close(); 40 | } 41 | }; 42 | }; 43 | class PgAdapter{ 44 | constructor(connectionString){ 45 | this.pool = new ConnectionPool(connectionString, 10); 46 | this.name = "Postgres Adapter"; 47 | }; 48 | save(item){ 49 | //need to really send to the DB... 50 | console.log("Saving to PG"); 51 | }; 52 | } 53 | 54 | const adapter = new PgAdapter("test"); 55 | console.log(adapter.pool); 56 | const conn = adapter.pool.checkout(); 57 | console.log(conn); 58 | -------------------------------------------------------------------------------- /Season2/05-encoding/lib/encoding.js: -------------------------------------------------------------------------------- 1 | class Encoding { 2 | constructor(){ 3 | //default props 4 | this.dictionary = {}; 5 | this.codeWords = {}; 6 | } 7 | 8 | characterSet(){ 9 | return Object.values(this.codeWords); 10 | } 11 | 12 | totalCharacters(){ 13 | let total = 0; 14 | //I know, this looks weird 15 | //it has to do with the way emojis have a string length of two 16 | //but the iterator only iterates them once so... yeah 17 | for(let word of this.dictionary){ 18 | for(let char of word) total+=1; 19 | } 20 | return total; 21 | } 22 | characterCounts(){ 23 | let result = {}; 24 | for(let word of this.dictionary){ 25 | for (let character of word) { 26 | if (result[character]) { 27 | result[character]++; 28 | } else { 29 | result[character] = 1; 30 | } 31 | } 32 | } 33 | return result; 34 | } 35 | 36 | kraftMacmillan(){ 37 | 38 | const bits = Object.keys(this.codeWords); 39 | return bits.reduce((total,b) => { 40 | const level = b.length 41 | //console.log("Level: ", level); 42 | const fraction = 1.00 / Math.pow(2,level); 43 | //console.log("Fraction: ", console.log(fraction)); 44 | //console.log(fraction); 45 | return total + fraction; 46 | },0) 47 | } 48 | 49 | levels(){ 50 | let result = {}; 51 | const keys = Object.keys(this.codeWords); 52 | for(let key of keys){ 53 | const level = key.length; 54 | result[this.codeWords[key]] = level; 55 | } 56 | return result; 57 | } 58 | } 59 | 60 | module.exports = Encoding; -------------------------------------------------------------------------------- /Season2/06-error-correction/parity.js: -------------------------------------------------------------------------------- 1 | const Encoder = require("./encoder"); 2 | const encoder = new Encoder(); 3 | 4 | //encoder.evenParity(); 5 | 6 | const message = `You want a toe? I can get you a toe, believe me. There are ways, Dude. You don't wanna know about it, believe me.` 7 | const encoded = encoder.encode(message); 8 | console.log(encoded); 9 | 10 | const encodedWithErrors = `010111000000011100000001100110000001000000000000001001000000010000000001011000000000001100000000000000000000010000000001000000000000001100000000011100000001101000000000000000000000110100000001000000000000001000000001010000000001011000000000000000000000010100000000101000000000001100000000000000000000010111000000011100000001100110000001000000000000010000000001000000000000001100000000011100000001101000000000000000000000100000000001101000000000100010000000110100000001101000000000010110100000101000000000000000000000010101000001101000000000000000000000001100000000110000000000101000000000111000000001101000000000000000000000010000000001111000000001101000000000000000000000001001000000010000000001010111000000111100000000000000000000001010000000100110000001001010000000101000000000000000000000010111000000011100000001100110000001000000000000001010000000011100000001011000000000001100000000000000000000001001000000010000000001011000000000011000000000010000000001000000000000010110010000011000000000011100000001001001000000000000000000010000000001100000000001011100000001100110000001001100000000000000000000110100000001001100000000000000000000100000000001101000000000100010000000110100000001101000000000010110100000101000000000000000000000010101000001101000000001` 11 | 12 | console.log(encoder.decode(encodedWithErrors)); -------------------------------------------------------------------------------- /Season2/08-hashes/blockchain.js: -------------------------------------------------------------------------------- 1 | const crypto = require("crypto"); 2 | 3 | const createHash = (block) => { 4 | //need to pass a string to our 5 | const hashValue = JSON.stringify(block) 6 | return crypto.createHash("sha256") 7 | .update(hashValue) 8 | .digest("base64"); 9 | } 10 | 11 | const mine = (block, difficulty = 2) => { 12 | let found = false, start = new Date().getTime(); 13 | //we're looking for a string of 0s so let's create the pattern 14 | //I could use Regex but I'm not that good 15 | const lookingFor = "0".padStart(difficulty, "0"); 16 | console.log("Looking for a hash starting with", lookingFor); 17 | const duration = new Date().getTime() - start; 18 | 19 | while(!found){ 20 | const possibleHash = createHash(block); 21 | //does the hash start with zeroes? 22 | found = possibleHash.substring(0, difficulty) === lookingFor; 23 | if(found){ 24 | block.hashKey = possibleHash; 25 | return block; 26 | } 27 | block.nonce += 1; 28 | //10 second kill switch 29 | if(duration > 10000) return "Didn't find it under 10s" 30 | } 31 | } 32 | 33 | const block = { 34 | transactions: [ 35 | {from: "me", to: "you", amount: 10.00}, 36 | {from: "you", to: "me", amount: 5.00} 37 | ], 38 | timestamp: 1609702546153, //if this changes the hash changes 39 | nonce: 0, 40 | previousKey: "00RSDThMVcQAvoocD3klO/6pjJ4a8pRbZ3ykk3XXhXE=" 41 | } 42 | //let's see how long this takes 43 | const start = new Date().getTime(); 44 | //let's do it! 45 | const result = mine(block, 4); 46 | const duration = new Date().getTime() - start; 47 | console.log(`That took duration ${duration}ms`); 48 | console.log(result); 49 | 50 | -------------------------------------------------------------------------------- /Season2/08-hashes/rsa.js: -------------------------------------------------------------------------------- 1 | //resources 2 | //https://www.cs.drexel.edu/~jpopyack/IntroCS/HW/RSAWorksheet.html 3 | //https://www.cryptool.org/en/cto/highlights/rsa-step-by-step 4 | 5 | //let's find two relatively prime numbers, e and d, such that 6 | //e % d mod r === 1 7 | //this is the cornerstone of RSA 8 | var findEandD = function(r) { 9 | //These are common candidates for e, which can be autoset 10 | //and typically 65537 is used, but we'll 11 | //start small for speed 12 | const possibleEs = [3n,5n,17n,257n,65537n] 13 | //now, loop over the possible e's so we can find our d 14 | for(let e of possibleEs){ 15 | //we want to find a coprime for e, so let's factor it 16 | //up to r and see if e % r is 1 17 | //if it is, we found our coprime 18 | for (let d = 1n; d < r; d++) { 19 | const candidate = e * d; 20 | if (candidate % r == 1n) return {e: e, d: d}; 21 | } 22 | } 23 | assert.fail("We shouldn't reach this point") 24 | } 25 | 26 | const p = 499n; 27 | const q = 491n; 28 | assert.notStrictEqual(p,q, "p and q must be different primes"); 29 | 30 | //our public key, N 31 | const N = p * q; 32 | 33 | //Euler's totient for deriving r 34 | //r = phi(n) = (p-1) * (q-1) 35 | const r = (p-1n) * (q-1n); 36 | 37 | //now we can calculate e and d for our private key 38 | const {e,d} = findEandD(r); 39 | 40 | //our message 41 | const M = 25n; 42 | 43 | console.log("e",e); 44 | console.log("d",d); 45 | console.log("N",N); 46 | console.log("r",r); 47 | 48 | console.log("M", M); 49 | 50 | //the RSA algorithm 51 | const encrypted = M**e % N; 52 | const decrypted = encrypted**d % N; 53 | 54 | console.log("Encrypted",encrypted); 55 | console.log("Decrypted",decrypted); -------------------------------------------------------------------------------- /Season2/01-binary-math/addition.js: -------------------------------------------------------------------------------- 1 | 2 | const and = (x, y) => x && y ? 1 : 0; 3 | const xor = (x, y) => x !== y ? 1 : 0; 4 | const halfAdder = (x, y) => [and(x, y), xor(x, y)]; 5 | const halfNadder = (x, y) => [or(x, y), equiv(x, y)]; 6 | 7 | const or = (x, y) => x || y ? 1 : 0; 8 | const not = x => x ? 0 : 1; 9 | 10 | //secondary 11 | 12 | const equiv = (x, y) => x === y ? 1 : 0; 13 | const imp = (x, y) => x === 1 ? y : 1; 14 | 15 | //complementatary 16 | const identity = (x, y) => not(not(x)); 17 | const nand = (x, y) => not(and(x, y)); 18 | const nor = (x, y) => not(or(x, y)); 19 | 20 | //complementary secondary 21 | const xnor = (x, y) => not(xor(x, y)); 22 | const nequiv = (x, y) => not(equiv(x, y)); 23 | const nimp = (x, y) => !x ? y : 1; 24 | 25 | //obligatory one-liner 26 | const fullAdder = (x, y, c = 0) => c ? halfNadder(x, y) : halfAdder(x, y); 27 | 28 | const binaryAddition = function (x, y) { 29 | //our output, which is a string and the carry bit 30 | let sum = "", c = 0; 31 | 32 | //handle length differences by padding the start with 0s 33 | if (x.length > y.length) y = y.padStart(x.length, "0"); 34 | if (y.length > x.length) x = x.padStart(y.length, "0"); 35 | 36 | //loop from right to left 37 | for (let i = x.length - 1; i >= 0; i--) { 38 | //get the current numbers for fullAdder 39 | const a = parseInt(x[i]), b = parseInt(y[i]); 40 | const [left, right] = fullAdder(a, b, c); 41 | //set the carry bit for next iteration 42 | c = left; 43 | //append the rightmost to our sum 44 | sum = right + sum; 45 | } 46 | //tack on a carry bit on the left end if needed 47 | return c ? c + sum : sum; 48 | } 49 | console.log(fullAdder(1,1,1)); 50 | console.log(binaryAddition('11011', '1111')); -------------------------------------------------------------------------------- /Season2/05-encoding/lib/shannon.js: -------------------------------------------------------------------------------- 1 | 2 | function messageLength(message){ 3 | //I know, this looks weird 4 | //it has to do with the way emojis have a string length of two 5 | //but the iterator only iterates them once so... yeah 6 | let total = 0; 7 | for(let word of message){ 8 | for(let char of word) total+=1; 9 | } 10 | return total; 11 | } 12 | 13 | exports.frequency = function(message){ 14 | let result = {}; 15 | for(let word of message){ 16 | for (let character of word) { 17 | if (result[character]) { 18 | result[character]++; 19 | } else { 20 | result[character] = 1; 21 | } 22 | } 23 | } 24 | return result; 25 | }; 26 | 27 | 28 | exports.probabilities = function(message){ 29 | let result = {}; 30 | let frequency = this.frequency(message); 31 | const totalChars = messageLength(message); 32 | 33 | for(let char of Object.keys(frequency)){ 34 | if(frequency[char]){ 35 | const prob = (frequency[char] / totalChars) 36 | result[char] = prob; 37 | } 38 | } 39 | 40 | return result; 41 | } 42 | 43 | exports.surprise = function(message){ 44 | let result = {}; 45 | let probability = this.probabilities(message); 46 | const chars = Object.keys(probability); 47 | 48 | for(let char of chars){ 49 | if(probability[char]){ 50 | result[char] = Math.log2(1/probability[char]) 51 | } 52 | } 53 | return result; 54 | } 55 | 56 | 57 | exports.entropy = function(message){ 58 | const surprises = Object.values(this.surprise(message)); 59 | const charCount = messageLength(message); 60 | const totalSurprise = surprises.reduce((total, s) => { 61 | return total + s 62 | },0); 63 | return totalSurprise/charCount; 64 | } 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /Season1/patterns/behavioral/chain_of_responsibility.js: -------------------------------------------------------------------------------- 1 | //Chain of Responsibility: wiring together a process 2 | //note: this is *not a current pattern that is used widely* 3 | //variations of this include event handling, piping through a process 4 | //and event source replay. 5 | class ShoppingCart{ 6 | constructor(){ 7 | this.items = []; 8 | //checkingOut 9 | //checkedOut 10 | //invalid 11 | this.status = "pending"; 12 | 13 | //no items 14 | this.isValid = false; 15 | this.errors = []; 16 | }; 17 | validate(){ 18 | const itemValidator = new ItemCountValidator(); 19 | const checkoutValidator = new CanCheckoutValidator(); 20 | //orchestrate the validation chain 21 | itemValidator.setSuccessor(checkoutValidator); 22 | //start it off 23 | itemValidator.validate(this); 24 | } 25 | }; 26 | class ShoppingCartValidator{ 27 | setSuccessor(nextValidator){ 28 | this.nextValidator = nextValidator; 29 | }; 30 | validate(cart){ 31 | console.log("Override this please"); 32 | }; 33 | handleNext(cart){ 34 | if(cart.isValid && this.nextValidator){ 35 | this.nextValidator.validate(cart); 36 | } 37 | }; 38 | }; 39 | class ItemCountValidator extends ShoppingCartValidator{ 40 | validate(cart){ 41 | cart.isValid = false; 42 | if(cart.items.length > 0) cart.isValid = true; 43 | else cart.errors.push("There are no items in the cart"); 44 | this.handleNext(cart); 45 | }; 46 | }; 47 | 48 | class CanCheckoutValidator extends ShoppingCartValidator{ 49 | validate(cart){ 50 | cart.isValid = false; 51 | if(cart.status !== "checkedOut") cart.isValid = true; 52 | else cart.errors.push("This cart is already checked out"); 53 | this.handleNext(cart); 54 | }; 55 | }; 56 | 57 | const cart = new ShoppingCart(); 58 | cart.items.push({sku: "socks"}); 59 | cart.status = "checkedOut"; 60 | cart.validate(); 61 | console.log(cart); 62 | -------------------------------------------------------------------------------- /Season2/03-negation/subtraction.js: -------------------------------------------------------------------------------- 1 | const and = (x, y) => x && y ? 1 : 0; 2 | const xor = (x, y) => x !== y ? 1 : 0; 3 | const halfAdder = (x, y) => [and(x, y), xor(x, y)]; 4 | const halfNadder = (x, y) => [or(x, y), equiv(x, y)]; 5 | const or = (x, y) => x || y ? 1 : 0; 6 | const not = x => x ? 0 : 1; 7 | const equiv = (x, y) => x === y ? 1 : 0; 8 | 9 | 10 | const fullAdder = (x, y, c = 0) => c ? halfNadder(x, y) : halfAdder(x, y); 11 | 12 | const addition = function (x, y) { 13 | //our output, which is a string and the carry bit 14 | let sum = "", c = 0; 15 | 16 | //handle length differences by padding the start with 0s 17 | if (x.length > y.length) y = y.padStart(x.length, "0"); 18 | if (y.length > x.length) x = x.padStart(y.length, "0"); 19 | 20 | //loop from right to left 21 | for (let i = x.length - 1; i >= 0; i--) { 22 | //get the current numbers for fullAdder 23 | const a = parseInt(x[i]), b = parseInt(y[i]); 24 | const [left, right] = fullAdder(a, b, c); 25 | //set the carry bit for next iteration 26 | c = left; 27 | //append the rightmost to our sum 28 | sum = right + sum; 29 | } 30 | //tack on a carry bit on the left end if needed 31 | return c ? c + sum : sum; 32 | } 33 | 34 | const onesComplement = function(num){ 35 | let inversion = []; 36 | for(let digit of num) { 37 | inversion.push(not(digit)) 38 | } 39 | return inversion.join("") 40 | } 41 | 42 | const twosComplement = function(num){ 43 | const ones = onesComplement(num) 44 | return addition(ones, "1"); 45 | } 46 | 47 | const simpleSubtraction = function(x,y){ 48 | //the idea here is that we're doing x - y 49 | //which is the same as x + -y 50 | const twos = twosComplement(y); 51 | const result = addition(x,twos); 52 | 53 | //if the left-most is 1 toss it, we don't carry 54 | return result.substring(1, result.length) 55 | } 56 | //27 - 15 57 | console.log(simpleSubtraction('11011', '01111')); //12 58 | -------------------------------------------------------------------------------- /Season1/functional/currying.js: -------------------------------------------------------------------------------- 1 | const dateNight = (who, what, where) => { 2 | return `Out with ${who} having fun ${what} at ${where}`; 3 | }; 4 | 5 | //curried, instead of one function with three args 6 | //three functions with an arity of 1, chained together 7 | const nightOut = what => who => where => { 8 | return `Out with ${who} having fun ${what} at ${where}`; 9 | }; 10 | const dancing = nightOut("Dancing"); 11 | const dancingWithWife = dancing("wife"); 12 | const funTime = dancingWithWife("Club 9") 13 | console.log(funTime); 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | // 34 | // const pgp = require('pg-promise')(); 35 | // const db = pgp("postgres://localhost/chinook"); 36 | // 37 | // //curried function 38 | // const nightOut = what => who => where => { 39 | // return `Out with ${who} having fun ${what} at ${where}`; 40 | // } 41 | // //partial application 42 | // const dancing = nightOut("dancing"); 43 | // const dancingWithWife = dancing("wifey"); 44 | // const dateNight = dancingWithWife("Club 9") 45 | // console.log(dateNight); 46 | // 47 | // //curried SQL 48 | // const selectQuery = table => (where, params=[]) => order => limit => exec => { 49 | // const whereClause = where ? ` where ${where}` : ""; 50 | // const orderClause = order ? ` order by ${order}` : ""; 51 | // const limitClause = limit ? ` limit ${limit}` : ""; 52 | // if(params.length > 0) params = [params]; 53 | // const sql = `select * from ${table}${whereClause}${orderClause}${limitClause}`; 54 | // const query = {sql: sql, params: params}; 55 | // if(exec){ 56 | // db.many(sql, params).then(res => exec(res)).catch(err => console.log(err)) 57 | // } 58 | // else return query; 59 | // }; 60 | // const albumQuery = selectQuery("album"); 61 | // const albumSearch = title => albumQuery("title LIKE $1", `%${title}%`)()(); 62 | // const rockAlbums = albumSearch("Rock"); 63 | // console.log(rockAlbums()); 64 | -------------------------------------------------------------------------------- /Season1/testing/tdd/billing_test.js: -------------------------------------------------------------------------------- 1 | //TDD: Subscription billing 2 | //Key Concepts: YAGNI, DRY, FUN!!! 3 | 4 | describe("Monthly Billing", function(){ 5 | var repo, billingSystem; 6 | before(function(){ 7 | repo = new CustomerRepo(); 8 | billingSystem = new BillingThingy(repo); 9 | }); 10 | describe("Customers with subs due", function(){ 11 | before(function(){ 12 | repo.customers = [{name: "Steve",subscriptions: [{plan:"gold"}]}]; 13 | }); 14 | //happy path 15 | it("are charged", function(){ 16 | const result = billingSystem.processMonth(2017, 2); 17 | assert.equal(result,1); 18 | }); 19 | }); 20 | describe("Customers without subs due", function(){ 21 | before(function(){ 22 | repo.customers = []; 23 | }); 24 | //sad path 25 | it("are not charged", function(){ 26 | const result = billingSystem.processMonth(2017, 2); 27 | assert.equal(result,0); 28 | }); 29 | }); 30 | describe("A Customer with two subs", function(){ 31 | before(function(){ 32 | repo.customers = [{name: "Steve", subscriptions: [{plan:"gold"}, {plan: "silver"}]}]; 33 | }); 34 | //sad path 35 | it("is billed twice", function(){ 36 | const result = billingSystem.processMonth(2017, 2); 37 | assert.equal(result,2); 38 | }); 39 | it("but only one customer is charged", function(){ 40 | assert.equal(repo.customers.length,1); 41 | }); 42 | }); 43 | }); 44 | class Customer{ 45 | constructor(){ 46 | this.subscriptions = []; 47 | } 48 | }; 49 | class CustomerRepo{ 50 | constructor(){ 51 | this.customers = []; 52 | } 53 | }; 54 | class BillingThingy{ 55 | constructor(repo){ 56 | this.customerRepo = repo; 57 | }; 58 | processMonth(year, month){ 59 | const customers = this.customerRepo.customers; 60 | var result = 0; 61 | for(var customer of customers){ 62 | result+=customer.subscriptions.length; 63 | } 64 | return result; 65 | } 66 | }; 67 | -------------------------------------------------------------------------------- /Season2/062-error-correction/encoder.js: -------------------------------------------------------------------------------- 1 | const Hamming = require("./hamming"); 2 | class Encoder{ 3 | 4 | constructor(){ 5 | 6 | this.encoding = { 7 | "A" : "01000000000", 8 | "B" : "10000000000", 9 | "C" : "00100000000", 10 | "D" : "00101000000", 11 | "E" : "10100000000", 12 | "F" : "10010000000", 13 | "G" : "01010000000", 14 | "H" : "11000000000", 15 | "I" : "11010000000", 16 | "J" : "01011000000", 17 | "K" : "01011001000", 18 | "L" : "10001000000", 19 | "M" : "01010100000", 20 | "N" : "01100000000", 21 | "O" : "01110000000", 22 | "P" : "10000100000", 23 | "Q" : "01011000100", 24 | "R" : "11100000000", 25 | "S" : "11110000000", 26 | "T" : "00110000000", 27 | "U" : "10011000000", 28 | "V" : "01011010000", 29 | "W" : "00100100000", 30 | "X" : "01011000110", 31 | "Y" : "01011100000", 32 | "Z" : "01011000111", 33 | " " : "00000000000" 34 | } 35 | } 36 | encode(message){ 37 | //loop the characters in the message 38 | //we'll assume for now that they won't enter anything but alpha numeric with a space for separation 39 | //also ... uppercase to reduce pain 40 | const words = message.toUpperCase(), out = []; 41 | 42 | for(let word of words){ 43 | for(let char of word){ 44 | const encoding = this.encoding[char]; 45 | //if the character can be encoded great. If not, ignore 46 | if(encoding) out.push(encoding); 47 | } 48 | } 49 | const rawMessage = out.join(""); 50 | return Hamming.calcParity(rawMessage); 51 | 52 | } 53 | getAlpha(binary){ 54 | return Object.keys(this.encoding).find(k => this.encoding[k] === binary) 55 | } 56 | 57 | decode(received){ 58 | const corrected = Hamming.correctAnyErrors(received) 59 | const cleaned = Hamming.removeParityBits(corrected); 60 | let out = [], codeWord = ""; 61 | const pad = this.encoding.A.length; 62 | for(let i = 0; i < cleaned.length; i+=pad){ 63 | codeWord = cleaned.substring(i, i + pad); 64 | const key = this.getAlpha(codeWord); 65 | out.push(key); 66 | codeWord = ""; 67 | } 68 | return out.join(""); 69 | } 70 | 71 | } 72 | 73 | module.exports = Encoder; -------------------------------------------------------------------------------- /Season2/00-boolean-algebra/operations.js: -------------------------------------------------------------------------------- 1 | var AsciiTable = require('ascii-table'); 2 | 3 | const truthTable = (op, fn) => { 4 | const tbl = new AsciiTable(`${op}`) 5 | tbl 6 | .setHeading("X", "Y", "Out") 7 | .addRow(0, 0, fn(0, 0)) 8 | .addRow(0, 1, fn(0, 1)) 9 | .addRow(1, 0, fn(1, 0)) 10 | .addRow(1, 1, fn(1, 1)); 11 | console.log(tbl.toString()); 12 | }; 13 | 14 | //primary operations 15 | const and = (x, y) => x && y ? 1 : 0; 16 | const or = (x, y) => x || y ? 1 : 0; 17 | const not = x => x ? 0 : 1; 18 | 19 | const xor = (x,y) => x !== y ? 1 : 0; 20 | const equiv = (x,y) => x === y ? 1 : 0; 21 | const imp = (x,y) => x === 1 ? y : 1; 22 | 23 | truthTable("AND", and); 24 | truthTable("OR", or); 25 | truthTable("XOR", xor); 26 | truthTable("EQUIV", equiv); 27 | truthTable("IMP", imp); 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | // const AsciiTable = require("ascii-table"); 52 | 53 | // const truthTable = (op, fn) => { 54 | // const tbl = new AsciiTable(`${op}`) 55 | // tbl 56 | // .setHeading("X", "Y", "Out") 57 | // .addRow(0, 0, fn(0,0)) 58 | // .addRow(0, 1, fn(0,1)) 59 | // .addRow(1, 0, fn(1,0)) 60 | // .addRow(1, 1, fn(1,1)); 61 | // console.log(tbl.toString()); 62 | // }; 63 | 64 | // //primary operations 65 | // const and = (x,y) => x && y ? 1 : 0; 66 | // const or = (x,y) => x || y ? 1 : 0; 67 | // const not = (x,y) => x ? 1 : 0; 68 | 69 | // truthTable("AND", and); 70 | // truthTable("OR", or); 71 | 72 | // //secondary operations 73 | //const xor = (x,y) => x !== y ? 1 : 0; 74 | //const equiv = (x,y) => x === y ? 1 : 0; 75 | //const imp = (x,y) => x === 1 ? y : 0; 76 | 77 | // truthTable("XOR", xor); 78 | // truthTable("Equivalence", equiv); 79 | // truthTable("Implication", imp); 80 | 81 | // //complementary 82 | // const identity = (x,y) => x; 83 | // const nand = (x,y) => not(and(x,y)); 84 | // const nor = (x,y) => not(or(x,y)); 85 | 86 | // truthTable("NAND", nand); 87 | // truthTable("NOR", nor); 88 | 89 | // //complementary secondary 90 | // const xnor = (x,y) => not(xor(x,y)); 91 | // const nequiv = (x,y) => not(equiv(x,y)); 92 | // const nimp = (x,y) => not(imp(x,y)); 93 | 94 | // truthTable("XNOR", xnor); 95 | // truthTable("NEQUIV", nequiv); 96 | // truthTable("NIMP", nimp); -------------------------------------------------------------------------------- /Season1/algorithms/dynamic_programming/dijkstra.js: -------------------------------------------------------------------------------- 1 | //Dijkstra: Shortest path calculation 2 | //on an edge-weighted, directed graph 3 | class MemoTable{ 4 | constructor(vertices){ 5 | this.S = {name: "S", cost: 0, visited: false}; 6 | this.table = [this.S]; 7 | for(var vertex of vertices){ 8 | this.table.push({name: vertex, cost: Number.POSITIVE_INFINITY, visited: false}); 9 | } 10 | }; 11 | getCandidateVertices(){ 12 | return this.table.filter(entry => { 13 | return entry.visited === false; 14 | }); 15 | }; 16 | nextVertex(){ 17 | const candidates = this.getCandidateVertices(); 18 | if(candidates.length > 0){ 19 | return candidates.reduce((prev, curr) => { 20 | return prev.cost < curr.cost ? prev : curr; 21 | }); 22 | }else{ 23 | return null; 24 | } 25 | }; 26 | setCurrentCost(vertex, cost){ 27 | this.getEntry(vertex).cost =cost; 28 | }; 29 | setAsVisited(vertex){ 30 | this.getEntry(vertex).visited = true; 31 | }; 32 | getEntry(vertex){ 33 | return this.table.find(entry => entry.name == vertex); 34 | }; 35 | getCost(vertex){ 36 | return this.getEntry(vertex).cost; 37 | }; 38 | toString(){ 39 | console.log(this.table); 40 | } 41 | }; 42 | const vertices = ["A", "B","C", "D", "E"]; 43 | const graph = [ 44 | {from : "S", to :"A", cost: 4}, 45 | {from : "S", to :"E", cost: 2}, 46 | {from : "A", to :"D", cost: 3}, 47 | {from : "A", to :"C", cost: 6}, 48 | {from : "A", to :"B", cost: 5}, 49 | {from : "B", to :"A", cost: 3}, 50 | {from : "C", to :"B", cost: 1}, 51 | {from : "D", to :"C", cost: 3}, 52 | {from : "D", to :"A", cost: 1}, 53 | {from : "E", to: "D", cost: 1} 54 | ] 55 | const memo = new MemoTable(vertices); 56 | const evaluate = vertex => { 57 | const edges = graph.filter(path => { 58 | return path.from === vertex.name; 59 | }); 60 | for(edge of edges){ 61 | const currentVertexCost = memo.getCost(edge.from); 62 | const toVertexCost = memo.getCost(edge.to); 63 | const tentativeCost = currentVertexCost + edge.cost; 64 | if(tentativeCost < toVertexCost){ 65 | memo.setCurrentCost(edge.to, tentativeCost); 66 | } 67 | }; 68 | memo.setAsVisited(vertex.name); 69 | const next = memo.nextVertex(); 70 | if(next) evaluate(next); 71 | } 72 | //kick it off from the source vertex 73 | evaluate(memo.S); 74 | memo.toString(); 75 | -------------------------------------------------------------------------------- /Season2/062-error-correction/hamming.js: -------------------------------------------------------------------------------- 1 | const getParityBitPositions = (message) => { 2 | let matrix={}; 3 | for(let i=1; i <= message.length; i = i * 2) { 4 | let taken=0; skipped=0; 5 | matrix[i] = []; 6 | for(let x = i; x <= message.length; x++){ 7 | if(taken < i) { 8 | matrix[i].push(x) 9 | taken+=1; 10 | }else{ 11 | skipped+=1; 12 | } 13 | if(skipped===taken) skipped = taken = 0; 14 | } 15 | } 16 | return matrix; 17 | } 18 | 19 | exports.removeParityBits = (message) => { 20 | const digits= message.split(''); 21 | const matrix = getParityBitPositions(message); 22 | const bitPositions = Object.keys(matrix); 23 | //gotta go in reverse here because the index positions will change as we mutate the array 24 | for(let i = bitPositions.length-1; i >=0; i--){ 25 | const bitPosition = bitPositions[i]; 26 | digits.splice(bitPosition-1, 1); 27 | } 28 | return digits.join(""); 29 | } 30 | 31 | const addParityPlaceholder = function(message){ 32 | const digits= message.split(''); 33 | const matrix = getParityBitPositions(message) 34 | //add parity bits "_" to positions that are powers of two 35 | //as parity bits. (positions 1, 2, 4, 8, 16, 32, 64, etc.) 36 | for(let b of Object.keys(matrix)){ 37 | //... 38 | digits.splice(b-1, 0, "_") 39 | } 40 | return digits.join(""); 41 | } 42 | 43 | exports.calcParity = (message) => { 44 | const withPlaceholders = addParityPlaceholder(message); 45 | const matrix = getParityBitPositions(withPlaceholders); 46 | const binaryMessage = withPlaceholders.split(''); 47 | 48 | for(let bitIndex of Object.keys(matrix)){ 49 | let thisCalc=0; 50 | for(let idx of matrix[bitIndex]){ 51 | if(binaryMessage[idx-1] === "1") thisCalc+=1; 52 | } 53 | // if(thisCalc % 2 > 0) console.log(`Setting B${bitIndex} to 1 because ${thisCalc}`) 54 | // else console.log(`Leaving B${bitIndex} as 0 because ${thisCalc}`); 55 | binaryMessage[bitIndex - 1] = thisCalc % 2 > 0 ? "1" : "0" 56 | } 57 | return binaryMessage.join("") 58 | } 59 | 60 | exports.correctAnyErrors = (received) => { 61 | let errorPosition =0, matrix = getParityBitPositions(received), binaryMessage = received.split(''); 62 | for(let idx of Object.keys(matrix)){ 63 | let dataBits = matrix[idx], dataBitSum = 0; 64 | for(let bit of dataBits){ 65 | const bitIdx = parseInt(bit) - 1; //no off by 1! 66 | dataBitSum+= parseInt(binaryMessage[bitIdx]); 67 | } 68 | if(dataBitSum % 2 !== 0) { //the error check 69 | errorPosition += parseInt(idx); //it's additive 70 | console.log("Found error with Parity bit",idx); 71 | } 72 | } 73 | if(errorPosition > 0){ 74 | //flip the error using the array of chars 75 | console.log("Correcting error at position",errorPosition-1); 76 | binaryMessage[errorPosition-1] = binaryMessage[errorPosition-1] === "1" ? "0" : "1"; 77 | } 78 | return binaryMessage.join(""); 79 | } 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /Season1/functional/monad.js: -------------------------------------------------------------------------------- 1 | //Functors and Monads 2 | //Using functions to help orchestrate... functions... 3 | //a monad is a functor, with the addition 4 | //of some logic to help you deal with problematic values 5 | //like null or undefined 6 | class Maybe{ 7 | constructor(val){ 8 | this.value = val; 9 | } 10 | isNothing(){ 11 | return this.value === null || this.value === undefined; 12 | } 13 | map(fn){ 14 | return this.isNothing() ? new Maybe(null) : new Maybe(fn(this.value)); 15 | } 16 | val(){ 17 | return this.isNothing() ? "" : this.value; 18 | } 19 | } 20 | Maybe.of = val => new Maybe(val); 21 | 22 | const selectQuery = table => (where, params=[]) => order => limit => exec => { 23 | const whereClause = Maybe.of(where).map(w => `where ${w}`).val(); 24 | const orderClause = Maybe.of(order).map(o => `order by ${o}`).val(); 25 | const limitClause = Maybe.of(limit).map(l => `limit ${l}`).val(); 26 | 27 | if(params.length > 0) params = [params]; 28 | //const sql = `select * from ${table}${whereClause}${orderClause}${limitClause}`; 29 | 30 | const sql = Maybe.of(`select * from ${table}`) 31 | .map(sql => `${sql} ${whereClause}`) 32 | .map(sql => `${sql} ${orderClause}`) 33 | .map(sql => `${sql} ${limitClause}`) 34 | .val(); 35 | 36 | const query = {sql: sql, params: params}; 37 | if(exec){ 38 | db.many(sql, params).then(res => exec(res)).catch(err => console.log(err)) 39 | } 40 | else return query; 41 | }; 42 | const albumQuery = selectQuery("album"); 43 | const albumSearch = title => albumQuery("title LIKE $1", `%${title}%`)()(); 44 | const rockAlbums = albumSearch("Rock"); 45 | console.log(rockAlbums()); 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | // class Maybe{ 67 | // constructor(val){ 68 | // this.__value = val; 69 | // } 70 | // isNothing(){ 71 | // return (this.__value === null || this.__value === undefined); 72 | // }; 73 | // map(fn){ 74 | // return this.isNothing() ? Maybe.of(null) : Maybe.of(fn(this.__value)); 75 | // }; 76 | // val(){ 77 | // return this.isNothing() ? "" : this.__value; 78 | // }; 79 | // } 80 | // Maybe.of = (val) => new Maybe(val); 81 | // 82 | // 83 | // 84 | // const selectQuery = table => (where, params=[]) => order => limit => { 85 | // 86 | // const whereClause = Maybe.of(where).map(w => `where ${w}`).val(); 87 | // const orderClause = Maybe.of(order).map(o => `order by ${order}`).val(); 88 | // const limitClause = Maybe.of(limit).map(l => `limit ${limit}`).val(); 89 | // 90 | // const sql = Maybe.of(`select * from ${table}`) 91 | // .map(sql => `${sql} ${whereClause}`) 92 | // .map(sql => `${sql} ${orderClause}`) 93 | // .map(sql => `${sql} ${limitClause}`) 94 | // .val(); 95 | // return {sql: sql, params: params}; 96 | // }; 97 | // const albumQuery = selectQuery("albums"); 98 | // const albumSearch = title => albumQuery("title LIKE $1", `%${title}%`)(); 99 | // const rockAlbums = albumSearch("Rock"); 100 | // console.log(rockAlbums()); 101 | -------------------------------------------------------------------------------- /Season2/06-error-correction/encoder_1.js: -------------------------------------------------------------------------------- 1 | class Encoder{ 2 | // constructor(){ 3 | // this.encoding = { 4 | // "A" : "01000000000", 5 | // "B" : "10000000000", 6 | // "C" : "00100000000", 7 | // "D" : "00101000000", 8 | // "E" : "10100000000", 9 | // "F" : "10010000000", 10 | // "G" : "01010000000", 11 | // "H" : "11000000000", 12 | // "I" : "11010000000", 13 | // "J" : "01011000000", 14 | // "K" : "01011001000", 15 | // "L" : "10001000000", 16 | // "M" : "01010100000", 17 | // "N" : "01100000000", 18 | // "O" : "01110000000", 19 | // "P" : "10000100000", 20 | // "Q" : "01011000100", 21 | // "R" : "11100000000", 22 | // "S" : "11110000000", 23 | // "T" : "00110000000", 24 | // "U" : "10011000000", 25 | // "V" : "01011010000", 26 | // "W" : "00100100000", 27 | // "X" : "01011000110", 28 | // "Y" : "01011100000", 29 | // "Z" : "01011000111", 30 | // " " : "00000000000" 31 | // } 32 | // } 33 | constructor(){ 34 | this.encoding = { 35 | "A" : "0100", 36 | "B" : "100000", 37 | "C" : "001000", 38 | "D" : "00110", 39 | "E" : "101", 40 | "F" : "10010", 41 | "G" : "010100", 42 | "H" : "1100", 43 | "I" : "1101", 44 | "J" : "010110000", 45 | "K" : "01011001", 46 | "L" : "10001", 47 | "M" : "010101", 48 | "N" : "0110", 49 | "O" : "0111", 50 | "P" : "100001", 51 | "Q" : "0101100010", 52 | "R" : "1110", 53 | "S" : "1111", 54 | "T" : "0011", 55 | "U" : "10011", 56 | "V" : "0101101", 57 | "W" : "001001", 58 | "X" : "01011000110", 59 | "Y" : "010111", 60 | "Z" : "01011000111", 61 | " " : "000" 62 | } 63 | } 64 | 65 | encode(message){ 66 | //loop the characters in the message 67 | //we'll assume for now that they won't enter anything but alpha numeric with a space for separation 68 | //also ... uppercase to reduce pain 69 | const words = message.toUpperCase(), out = []; 70 | 71 | // //pad the encoding so it's 11 total chars 72 | // const keys = Object.keys(this.encoding); 73 | // for(let key of keys){ 74 | // this.encoding[key] = this.encoding[key].padEnd(11, "0"); 75 | 76 | // } 77 | 78 | for(let word of words){ 79 | for(let char of word){ 80 | const encoding = this.encoding[char]; 81 | //if the character can be encoded great. If not, ignore 82 | if(encoding) out.push(encoding); 83 | } 84 | } 85 | return out.join(""); 86 | } 87 | getAlpha(binary){ 88 | return Object.keys(this.encoding).find(k => this.encoding[k] === binary) 89 | } 90 | decode(binaryMessage){ 91 | 92 | let out = [], codeWord = "", errors = []; 93 | 94 | for(let i = 0; i < binaryMessage.length; i+=11){ 95 | codeWord = binaryMessage.substring(i, i + 11); 96 | const key = this.getAlpha(codeWord); 97 | if(key){ 98 | out.push(key); 99 | codeWord = ""; 100 | }else{ 101 | //this is an error! 102 | //errors.push(key); 103 | const fix = this.simpleHammingErrorCorrector(codeWord); 104 | out.push(fix.word); 105 | } 106 | } 107 | 108 | return out.join(""); 109 | } 110 | 111 | simpleHammingErrorCorrector(binaryMessage){ 112 | 113 | const codeWords = Object.values(this.encoding); 114 | let bestCandidate = {}, bestDistance = Number.POSITIVE_INFINITY; 115 | 116 | for(let codeWord of codeWords){ 117 | let thisDistance = 0;; 118 | 119 | //we're scanning each word for a match 120 | for(let i = 0; i < codeWord.length; i++){ 121 | if(codeWord[i] !== binaryMessage[i]) { 122 | thisDistance+=1; 123 | } 124 | } 125 | 126 | if(thisDistance < bestDistance){ 127 | bestDistance = thisDistance; 128 | bestCandidate = {word: this.getAlpha(codeWord), binary: codeWord, distance: bestDistance} 129 | } 130 | } 131 | return bestCandidate; 132 | } 133 | // decode(binaryMessage){ 134 | 135 | // let out = [], codeWord = "", errors = []; 136 | 137 | // for(let bit of binaryMessage){ 138 | // codeWord+=bit; 139 | // const key = Object.keys(this.encoding).find(k => this.encoding[k] === codeWord) 140 | // if(key){ 141 | // out.push(key); 142 | // codeWord = ""; 143 | // } 144 | // } 145 | 146 | // return out.join(""); 147 | // } 148 | 149 | } 150 | 151 | module.exports = Encoder; -------------------------------------------------------------------------------- /Season2/06-error-correction/encoder.js: -------------------------------------------------------------------------------- 1 | class Encoder { 2 | constructor() { 3 | this.encoding = { 4 | A: "01000000000", 5 | B: "10000000000", 6 | C: "00100000000", 7 | D: "00101000000", 8 | E: "10100000000", 9 | F: "10010000000", 10 | G: "01010000000", 11 | H: "11000000000", 12 | I: "11010000000", 13 | J: "01011000000", 14 | K: "01011001000", 15 | L: "10001000000", 16 | M: "01010100000", 17 | N: "01100000000", 18 | O: "01110000000", 19 | P: "10000100000", 20 | Q: "01011000100", 21 | R: "11100000000", 22 | S: "11110000000", 23 | T: "00110000000", 24 | U: "10011000000", 25 | V: "01011010000", 26 | W: "00100100000", 27 | X: "01011000110", 28 | Y: "01011100000", 29 | Z: "01011000111", 30 | " ": "00000000000", 31 | }; 32 | } 33 | encode(message) { 34 | //loop the characters in the message 35 | //we'll assume for now that they won't enter anything but alpha numeric with a space for separation 36 | //also ... uppercase to reduce pain 37 | const words = message.toUpperCase(), 38 | out = []; 39 | 40 | for (let word of words) { 41 | for (let char of word) { 42 | const encoding = this.encoding[char]; 43 | //if the character can be encoded great. If not, ignore 44 | if (encoding) out.push(encoding); 45 | } 46 | } 47 | return out.join(""); 48 | } 49 | 50 | evenParity() { 51 | const keys = Object.keys(this.encoding); 52 | for (let key of keys) { 53 | //default to even 54 | let pad = "0"; 55 | //split into a character array so we can filter 56 | const chars = this.encoding[key].split(""); 57 | const ones = chars.filter((v) => v === "1"); 58 | //check mod 2 to see if we're odd, if so, set the pad to 1 59 | if (ones.length % 2 !== 0) pad = "1"; 60 | //update the encoding with a pad at the end 61 | this.encoding[key] += pad; 62 | } 63 | console.log(this.encoding); 64 | } 65 | checkParity(word) { 66 | //make sure we have the right length 67 | if (word.length !== 12) return false; 68 | //now make sure it's even 69 | return word.split("").filter((char) => char === "1").length % 2 === 0; 70 | } 71 | encode(message) { 72 | //loop the characters in the message 73 | //we'll assume for now that they won't enter anything but alpha numeric with a space for separation 74 | //also ... uppercase to reduce pain 75 | const words = message.toUpperCase(), 76 | out = []; 77 | 78 | for (let word of words) { 79 | for (let char of word) { 80 | const encoding = this.encoding[char]; 81 | //if the character can be encoded great. If not, ignore 82 | if (encoding) out.push(encoding); 83 | } 84 | } 85 | return out.join(""); 86 | } 87 | getAlpha(binary) { 88 | return Object.keys(this.encoding).find((k) => this.encoding[k] === binary); 89 | } 90 | 91 | decode(binaryMessage) { 92 | let out = [], 93 | codeWord = ""; 94 | const pad = this.encoding.A.length; 95 | for (let i = 0; i < binaryMessage.length; i += pad) { 96 | codeWord = binaryMessage.substring(i, i + pad); 97 | const noError = this.checkParity(codeWord); 98 | 99 | if (noError) { 100 | const key = this.getAlpha(codeWord); 101 | out.push(key); 102 | codeWord = ""; 103 | } else { 104 | //this is an error! 105 | console.log("Got an error with ", codeWord); 106 | const fix = this.simpleHammingErrorCorrector(codeWord); 107 | console.log("Fixing with best guess:", fix); 108 | out.push(fix.word); 109 | } 110 | } 111 | return out.join(""); 112 | } 113 | simpleHammingErrorCorrector(binaryMessage) { 114 | const codeWords = Object.values(this.encoding); 115 | let bestCandidate = {}, 116 | bestDistance = Number.POSITIVE_INFINITY; 117 | 118 | for (let codeWord of codeWords) { 119 | let thisDistance = 0; 120 | 121 | //we're scanning each word for a match 122 | for (let i = 0; i < codeWord.length; i++) { 123 | if (codeWord[i] !== binaryMessage[i]) { 124 | thisDistance += 1; 125 | } 126 | } 127 | if (thisDistance < bestDistance) { 128 | bestDistance = thisDistance; 129 | bestCandidate = { 130 | word: this.getAlpha(codeWord), 131 | binary: codeWord, 132 | distance: bestDistance, 133 | }; 134 | } 135 | } 136 | return bestCandidate; 137 | } 138 | } 139 | 140 | module.exports = Encoder; 141 | -------------------------------------------------------------------------------- /Season2/07-encryption/data/pads.js: -------------------------------------------------------------------------------- 1 | 2 | //Each pad is 5000 chars in length 3 | module.exports = [ 4 | "MNVEBWXXCAEEQETLUULLGGTBHDCPQMHVFMCUGNNLLGRAGSGDLNZKTBDUMQSDYYPGXYMCCVMANEZUWMZJNHEFEXXDWJKLEEQZYCPYDBZHYWTELMBCBLFMSHMQJVKSZXMYTXVWLVZUZPTXTVHAJBFCWDALYZEGSQRKCWDPFEEGFERBXAKXMDZPQCQKHCXMLCQRVGEYAHXNQUMTSNZVVRCCMSZBJHMRRAPCUZGHZJGTNVXKADKBHNPXZEKLTFFFNCBRDUAZPSNNRZQGYGDERPCHPUQEEXSLMBDUPNRWCENKUVMXDUSPZJXLXEVENMDTFEWHJTYKPZCQEVTDKWUJLWDXQQAKKLDXQTPTYVUYEJCMBPCAXPMLLKYHUFSAXHTFBWEJWQVZMPHAASDBXMQDERYAPKCFCTSYQGQHXFCYGEUDEWLZWQGBSJAAAAQETJEAYLGWEZGDWNZLFQXQTPXDAWZDMNQXKHSVTYYBJLCYDUPNPJQZUJZGJPSC", 5 | "BHTPSPMSLZJFRQXUEMBCBBKWKSQQUBCFCMHPBQXSBSSSDVXWGVSZVCJEHCEDMKUDQTXUGEZXJSFLYUEZNAMLDRUZRWDWNZQMGBEJGZVWALDUWLHLBKVGJUGHESMDMDYKQDXRYADEFJLBGBZDKDFBWCKAGTJBBPBJCWMESDYAUTSHRQJHGRHAXHWRVYKLNTGCRBMFFVZXVELSNGVPQSNGPDBVXJBPCFUNJRECQKATWMJXEPJETHTBWBSJRWAVCUPSCWCRRBBWWNUEYXSDXYBPUHYNDMCXWCJTUJCTUFDJUVVNDLECWSAQPJPPUACDBDFNDSNCRRNMXQEELHVFWNUZTSFLQRKBFNJPMQBPTYQQYCSDXXQBKNGMEGCSXARKTPGVAKRXZMDRXNZQYSMNZCSWWZGPULDBBELPBSUKAAGGDDWLLSGAXTYNLQAKGLKNBVZXBSYYAZJSVFYACQGULBDFDKWXDMPKRPFAZMQKKLUFDVGESBJJABCK", 6 | "MFLEXLKSVXFBMYVVHCBTQAXCXXETUWLJLHYNUDCNWLZDPWBTWHHHQSTGXZSXRBCELQZWDYNHUJTMFLWNBDZAYPTWYLXQMUWQYNXFXMLLLYETKGCZFMNGJUSEWBBGXPPXKCRMTKQGBZSSLJZFLXCSSWHQPVSLCTYHHGJYMHVJKKLENGLPMUMEJBEULNFJFWRDKXTCUBUHRDHKQDZECGSZJKEQHVGLMXDNZDZHKPUBVCJXZPJADTVKFUJMJQHLZNWWDEHVSUXFYUETJBBFKUHKMJGECHLSENQLREGAJLEWZATEWPPPURGKABJLMPREMATYBCWQDMYWXWXPBULENYMHZEDKBESRHBAMZKXQWRUQQRELLQMPXRMKFLEZGPXPPYJWBBXVXRBGGJRLCBUYBXAVSAMSUFECVUMVLXCKDMBDZGRBXTAHCBQCYDRKHRWNBXYUWDRZDUWHHMUTSFKZDYLNZHSRQBLPVPAKLKCWDMWZAZSSTKPWTYUS", 7 | "NGBNWKXDGGHWLVNDLUUENQUNUCNGULHHLNDXEHLPULEZTGFTZALBPFTJKAPGLFJWKXCLGYHHZKJBSPUKKXKLVSAVECNWNAQUPKUBDEZWWLLYJDKKNBHQSKCZNCBTWMSELUYYABSUFALTSUFNVZNGDLNPHQBBCZFYLGZASUPTVVWAXKLVRZDKTTKMDLWLEEWNVSUXZYBZHJKBNQPBWAMYPMTCRVEZELHGREPUSRHSMAVETABSNZYMWAYNZLPJHXDBBNHPUNCMTPCWTLBVLKHJZDTCEARFZFBYTESMSUPFWNSUAMNSXUUVVMYSLRNBFFFRRVXNGGXMEKNQXQLTJTRJBLVQVPVGCHZSHMUTRMALFJDBAQLCFLUHNXQPTTXJPFGFLZWENFUAUWXXRTXYNDBVFXKFHZCDWJZWHKMHDZDHTKHNAUWTSLGVYCRKLYWMLJUWKDNYNFUGBGWYHQCHJJTKECDSYVAWDABASUTKHMWSBPJWULCQMCRU", 8 | "YLDWPRYYPXNCHQPBWCBUUWXJTZZVGQFZZGHCSWRDAEJCKBWFVFPBDZCPBRMTRJRCGTMPYYKZZQTUYJGJXKMLRUVNJDXEWBXRBGJKLHCQFJGFWHQXPEGJALMPZSACXNYKYAEUXMBHKTPPBJDKJTAPZCGQNPKWBDAEKWTYCMMEBBXGHHTGWZQZKESVKXHDLLLSCUTHKCQKLPAQGPXGUZLXPNMABJJKLWWDNEGKUPACGLREWCVMVEEWPZMBZVCAVMHPWBENNHDPJTEKUJSMVHKMERZVVDNRSFSXHSPGWFXAGCNDKCVSAHRUZMLLZPRUGAETLHASXGNELUFXLNRNCFPBALSRUWFTBBWZRHBDGTZATYELWGZZLPPBNGEFCYEDLFEUTSCGTMDQXRELZBCAJKUFYWNDHEWVPXMMJSRUEUSCTQBBGNLHLSHGDGYEPTNHJMNPNHVAFPQZJRTRLHSQRMTHLNXTLGTVQLCKFLLXEDTKSZLXNBZYBCCP", 9 | "YXRQKDRRNDSXXCSWJUNWLKZJPVNWEYTHLDLKDUTRVCJLAWEQBAXLEYJRSTZDXCHMELSLLSYTJZZXNFNXKNTNFZUQNJPEHYJMPLTGMRRMTRPUMRLGMBRCHAWNUDBSLWHZYTCXFPKARSEZFSFMMTVDFZVVLCPPQHTDLCNRSASRSVDENTKPXKHYPWCMGFNRXCHHUTKUZDPEGYTMFWDBAJRBAYFTDHSCDSXRMUHBLHGBUYSWQLTPMSPVJQCQJJXDMCMSSTMWWDGTHPYTSVYLPUVUXYSZUSJUCKUPNPBMECVVWMLYWNFWZPCZZCMYEVMNSQDQQJQLGCAGBDBAMSZRXSGZYXDXFAMPMUDRMUFXUQXHJPTPYZSFDZVXZQNMSBDTUWSEFECWUFYDTXFURVAYPNYMUJBYCXRWVPLDHTXGKEQBQCNKLEXLJSPXHLXMUEHWBPJAKEBTFERJVVPPQTWWVVRQGZHRLUEPCLRFNKAYPSGUDHVFNUUFJYLD", 10 | "XEAGJKZVYKLQKFBTBBTGJNRQCQQKGHJBFQJTCHHBUEPNGWYGDAAWDVBJJQULBXNUCQTFSLHRUNJQJWWTYTCEQTGGXYVCESEQUFHYVSGNYETJMMAPMCLBSHQHDYSQHCWJBKZYQBEKSBYFXYKRKKKUYHCQPPPUMEPVWHJTGDCMLQSBCFFNJWDJHLNFJPHHKYGTUZTCNWTRQHUMAVGMQGNBKUGPWKSNUPGWCXGLERUDDBPUDQLMYMLWGAYPELJXNTJJZFZQAPQTLNZWEYXWLDQEZCRQBLQCYWJEKLFRQUJECZDMMYLQFTJSQYNTLJDLYWDAVBZVXNLRVKZXHKYTVYGYASENQLQMYQMAMTVYSLAVXRWQQBCNZLGGGWYVUYVZRWAGFKQNFPFSCLFMJXERSLHKCTMMVGDXWUTHTMCETFBJACVUQAMZNLDGMEQCZUTXFMSMUVARMNYDCXFXNXFNQNRESMLVKLGBJTADZEWUFNAKHPEJNBPGBSLF", 11 | "YTCXCRBHPRFQDHAQGHYPLZJWWXNUDNWSQVBPZYSJHJAMGYYZEZZCVJSUSDNXPYEUHTEJGJLFSDHLEWAZJTZLKXHRNDDPUNDHKFRKPCFCVKACRWZPUUCYGUCJKESNFZYLLXBDWLAJENJBFAZJGCKGUSGPGYTTMFUAEJBTLLMJHAGZWFSWXBLCHLPBFVXQFBLUPERWWVWLCVBPNEGGYGVQZBZWQBQGNVNEXUGUTLZMZYXMSWZTGWQDUJZUBZLMJQGGLTKSURLPMRQBDRYLYQYJRLNDPCMWUQVVMTMVBWPWKUJPRGHNLTSQCYPXTWBKLYDSZBMFNCLCCVWWQSZDVMVRFGJRWBXURJUKCEYTPFNVNXUBDBRYEVBVTGNDEYUZWGMEXVFDWWYADJQJQXHKARJYGXQPXCNJRECMVZSAZDYABTTZSNTTFHQRRWWRTYAKFLDXKPLKZSQKKQFDZYCYJRYKWJWVWKNVWVQSJSGTMTLDJYGEQZVLEPEV", 12 | "JJSJBCHSRVLBNVAYATSSUBFNLBLPDDQPLFRLSRHDJTKRGSPVKSFKKXNRGLRJBHWKCYDMYYBMTMNYQXBMNBSZKXWLJSMYZAUBECZSSLQBWTPHMPSPXXTVSPMMFURXQBZKEUZHGXHQGTEDDBQVDTZLKACADLFUPXJALVCPAKUZMNVMQZZRERGWLHMFJAVHYJFJWTQVDJPVKHQQBFJEKVZTTKYZGCXJWLCREUMANWEWCRXEKKZRTZLJBBANVSTZSRRHYJQEPJXHTRLKYBCZSNTAQHVLPLFNHVGGSZXGVPVFYQVALKAAPZTUUBZQHGTWGJAHQHYGZSYDCPYBESLWBWGMCFCVKKPVUPVMLARYHUFHJFTZPCGLKVWBDAQVGYWEJRFTHXMGYFEZJBXAREEGEACHZWYZERHPNTBCCRBUNXACJXREVPNSFKNVLDVKHXRTPQMTFGPXUKPYNJUMLNBMAMHMGJHNHRANVQPELYHATUWKTMZSERBWFFXW", 13 | "TPUAWSHNZGMGBRFUHUVFHQYHKAGTYZJYZSJFQZTDAPAEFPWBDAMYFRNSYMLGEZMURPLVYXVNHPVUYCLRSKNPLKHMQFFDKFABCUZRGPNGCVYDFHCSGSHPQYNBGTJXQPPWYWZRSDRQBVHYZWUSTAZHCVXMGTXVGSZDUUTAHXBVBFGHLKSWJWMPQSFFKBFUHHEUYTMQYBEXLWYJBCYLTSJRNSNGWXWZVFFHLHMCNMCEVYHWDSXEXPTBHPDSGPKWRKXFHKBJDWPMVFHSCHCQKJXEWJUZCZMPCASABNRHLXMUVCXQCUQAUCLKFFQRZWXXWQUKYWCHKUELTGTMAJHQQABFTEKEZNYWNWNKJGUXNRXCJWWBVAVHJWKHNEPQRERPRTKGXKENWHBMDXBXAQGBWTPYWBXLWHZWJTXLJJNQPYBFGPXTHNQMJYWXEMYWZERTMYCNADKGJKLAMGXCCTTZJYDSNDUWXFTRNFSKSZBAFXPUJZWHNUGAXPBB", 14 | ] -------------------------------------------------------------------------------- /Season2/05-encoding/tale_of_two_cities.txt: -------------------------------------------------------------------------------- 1 | It was the best of times it was the worst of times it was the age of wisdom it was the age of foolishness it was the epoch of belief it was the epoch of incredulity it was the season of Light it was the season of Darkness it was the spring of hope it was the winter of despair we had everything before us we had nothing before us we were all going direct to Heaven we were all going direct the other way in short the period was so far like the present period that some of its noisiest authorities insisted on its being received for good or for evil in the superlative degree of comparison only There were a king with a large jaw and a queen with a plain face on the throne of England there were a king with a large jaw and a queen with a fair face on the throne of France In both countries it was clearer than crystal to the lords of the State preserves of loaves and fishes that things in general were settled for ever It was the year of Our Lord one thousand seven hundred and seventyfive Spiritual revelations were conceded to England at that favoured period as at this Mrs Southcott had recently attained her fiveandtwentieth blessed birthday of whom a prophetic private in the Life Guards had heralded the sublime appearance by announcing that arrangements were made for the swallowing up of London and Westminster Even the Cocklane ghost had been laid only a round dozen of years after rapping out its messages as the spirits of this very year last past supernaturally deficient in originality rapped out theirs Mere messages in the earthly order of events had lately come to the English Crown and People from a congress of British subjects in America which strange to relate have proved more important to the human race than any communications yet received through any of the chickens of the Cocklane brood France less favoured on the whole as to matters spiritual than her sister of the shield and trident rolled with exceeding smoothness down hill making paper money and spending it Under the guidance of her Christian pastors she entertained herself besides with such humane achievements as sentencing a youth to have his hands cut off his tongue torn out with pincers and his body burned alive because he had not kneeled down in the rain to do honour to a dirty procession of monks which passed within his view at a distance of some fifty or sixty yards It is likely enough that rooted in the woods of France and Norway there were growing trees when that sufferer was put to death already marked by the Woodman Fate to come down and be sawn into boards to make a certain movable framework with a sack and a knife in it terrible in history It is likely enough that in the rough outhouses of some tillers of the heavy lands adjacent to Paris there were sheltered from the weather that very day rude carts bespattered with rustic mire snuffed about by pigs and roosted in by poultry which the Farmer Death had already set apart to be his tumbrils of the Revolution But that Woodman and that Farmer though they work unceasingly work silently and no one heard them as they went about with muffled tread the rather forasmuch as to entertain any suspicion that they were awake was to be atheistical and traitorous In England there was scarcely an amount of order and protection to justify much national boasting Daring burglaries by armed men and highway robberies took place in the capital itself every night families were publicly cautioned not to go out of town without removing their furniture to upholsterers warehouses for security the highwayman in the dark was a City tradesman in the light and being recognised and challenged by his fellowtradesman whom he stopped in his character of the Captain gallantly shot him through the head and rode away the mail was waylaid by seven robbers and the guard shot three dead and then got shot dead himself by the other four in consequence of the failure of his ammunition after which the mail was robbed in peace that magnificent potentate the Lord Mayor of London was made to stand and deliver on Turnham Green by one highwayman who despoiled the illustrious creature in sight of all his retinue prisoners in London gaols fought battles with their turnkeys and the majesty of the law fired blunderbusses in among them loaded with rounds of shot and ball thieves snipped off diamond crosses from the necks of noble lords at Court drawingrooms musketeers went into St Giless to search for contraband goods and the mob fired on the musketeers and the musketeers fired on the mob and nobody thought any of these occurrences much out of the common way In the midst of them the hangman ever busy and ever worse than useless was in constant requisition now stringing up long rows of miscellaneous criminals now hanging a housebreaker on Saturday who had been taken on Tuesday now burning people in the hand at Newgate by the dozen and now burning pamphlets at the door of Westminster Hall today taking the life of an atrocious murderer and tomorrow of a wretched pilferer who had robbed a farmers boy of sixpence All these things and a thousand like them came to pass in and close upon the dear old year one thousand seven hundred and seventyfive Environed by them while the Woodman and the Farmer worked unheeded those two of the large jaws and those other two of the plain and the fair faces trod with stir enough and carried their divine rights with a high hand Thus did the year one thousand seven hundred and seventyfive conduct their Greatnesses and myriads of small creaturesthe creatures of this chronicle among the restalong the roads that lay before them -------------------------------------------------------------------------------- /Season2/06-error-correction/hamming.js: -------------------------------------------------------------------------------- 1 | 2 | const getParityBitPositions = (message) => { 3 | const bits=[]; 4 | for(let i=1; i <= message.length; i = i * 2) { 5 | bits.push(i); 6 | } 7 | return bits; 8 | } 9 | 10 | const addParityPlaceholder = function(message){ 11 | const digits= message.split(''); 12 | const bits = getParityBitPositions(message) 13 | //add parity bits "P" to positions that are powers of two as parity bits. (positions 1, 2, 4, 8, 16, 32, 64, etc.) 14 | for(let b of bits){ 15 | //... 16 | digits.splice(b-1, 0, "P") 17 | } 18 | return digits.join(""); 19 | } 20 | 21 | 22 | //this is O(n*m) which isn't very good, but it's not the worst thing I guess 23 | //not sure if we can get around it but maybe if it was huge and stored somewhere 24 | const parityMatrix = function(message){ 25 | const length = message.length; 26 | const out={}, bits = getParityBitPositions(message) 27 | 28 | for(let b of bits){ 29 | const intBit = parseInt(b); 30 | let checked=0;skipped=0; 31 | 32 | //we'll return a hash with an array value of data placeholders 33 | out[intBit]=[]; 34 | 35 | for(let x = intBit; x <= length; x++){ 36 | if(checked < intBit) { 37 | out[intBit].push(x) 38 | checked+=1; 39 | }else{ 40 | skipped+=1; 41 | } 42 | 43 | if(skipped===checked){ 44 | skipped = 0; 45 | checked = 0; 46 | } 47 | } 48 | } 49 | return out; 50 | } 51 | 52 | 53 | const calcParity = (message) => { 54 | const withPlaceholders = addParityPlaceholder(message); 55 | const bits = getParityBitPositions(withPlaceholders); 56 | const matrix = parityMatrix(withPlaceholders) 57 | const binaryMessage = withPlaceholders.split(''); 58 | 59 | for(let bitIndex of bits){ 60 | let thisCalc=0; 61 | for(let idx of matrix[bitIndex]){ 62 | if(binaryMessage[idx-1] === "1") thisCalc+=1; 63 | } 64 | if(thisCalc % 2 > 0) console.log(`Setting B${bitIndex} to 1 because ${thisCalc}`) 65 | else console.log(`Leaving B${bitIndex} as 0 because ${thisCalc}`); 66 | binaryMessage[bitIndex - 1] = thisCalc % 2 > 0 ? "1" : "0" 67 | } 68 | return binaryMessage.join("") 69 | } 70 | 71 | const correctAnyErrors = (received) => { 72 | 73 | const matrix = parityMatrix(received) 74 | const binaryMessage = received.split(''); 75 | const parityIndexes = Object.keys(matrix); 76 | 77 | let errorPosition =0; 78 | for(let idx of parityIndexes){ 79 | 80 | const thisSegment = matrix[idx]; 81 | 82 | let calc = 0; 83 | for(let bit of thisSegment){ 84 | //console.log(binaryMessage[bit]); 85 | const bitIdx = parseInt(bit) - 1; 86 | calc += parseInt(binaryMessage[bitIdx]); 87 | } 88 | if(calc % 2 !== 0) console.log("Found error with Parity bit",idx); 89 | if(calc % 2 !== 0) errorPosition += parseInt(idx); 90 | 91 | } 92 | if(errorPosition > 0){ 93 | //flip the error using the array of chars 94 | console.log("Correcting error at position",errorPosition-1); 95 | binaryMessage[errorPosition-1] = binaryMessage[errorPosition-1] === "1" ? "0" : "1"; 96 | } 97 | return binaryMessage.join(""); 98 | } 99 | 100 | const randomlyFlipAbit = function(message,n){ 101 | const binaryMessage = message.split(""); 102 | console.log("Flipping at",n); 103 | binaryMessage[n] = binaryMessage[n] === "1" ? "0" : "1"; 104 | return binaryMessage.join("") 105 | } 106 | 107 | const message = `010111000000111000000010011000000000000000000010010000001000000000011000000000011000000000000000000010000000000000000000000110000000011100000001010000000000000000000110100000000000000000000100000000010000000000110000000000000000000010100000001010000000000110000000000000000000101110000001110000000100110000000000000000001000000000000000000000011000000001110000000101000000000000000000010000000000101000000001000100000011010000000101000000000101101000010100000000000000000000101010000010100000000000000000000011000000011000000000101000000001110000000010100000000000000000000100000000011100000000101000000000000000000000100100000010000000000101110000011110000000000000000000010100000010011000000001010000001010000000000000000000010111000000111000000010011000000000000000000010100000001110000000011000000000011000000000000000000001001000000100000000001100000000011000000000100000000000000000000010110010000110000000001110000000001001000000000000000001000000000100000000000111000000010011000000001100000000000000000011010000000001100000000000000000010000000000101000000001000100000011010000000101000000000101101000010100000000000000000000101010000010100000000` 108 | //const message = `010111011110011000001001010001100011000010000000110111101000110100000100001000110000010100101001100001011101111001100001000000011011110100010000010110001110110101011011010000101011010000011110010111101010000100111010100000100101000101111111000001011001100101101000010111011110011000001010111011000110000010010100011001100100000010110010110011100100100001001000000111100110011000110100110001000001011000111011010101101101000010101101` 109 | //console.log(message); 110 | const paritied = calcParity(message); 111 | //console.log(paritied); 112 | 113 | // const withBitPlaceholders = addParityPlaceholder(message); 114 | // const messageWithParity = calcParity(withBitPlaceholders); 115 | const paritiedWithErrors = randomlyFlipAbit(paritied,58); 116 | 117 | // console.log(messageWithParity); 118 | // console.log(paritiedWithErrors); 119 | 120 | const fixed = correctAnyErrors(paritiedWithErrors); 121 | // console.log(fixed); 122 | const areEqual = paritied === fixed; 123 | console.log("Are they equal?",areEqual); 124 | //whatAreMyParityBits(messageWithParity) 125 | //console.log(messageWithParity); 126 | //console.log(res); 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /Season2/05-encoding/index.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const frequency = function(message){ 4 | let calc = {}, sorter = [], out = {}; 5 | 6 | //calculate the counts using a hash for speed 7 | for(let word of message){ 8 | for (let character of word) { 9 | calc[character] ? calc[character]++ : calc[character] = 1; 10 | } 11 | } 12 | //pop into an array so we can sort 13 | for (var char in calc) { 14 | sorter.push([char, calc[char]]); 15 | } 16 | //sort descending based on the value 17 | sorter.sort((a, b) => b[1] - a[1]); 18 | //reassemble into an object, convenience mostly 19 | sorter.forEach(item => out[item[0]]=item[1]) 20 | return out; 21 | }; 22 | 23 | 24 | //compensating for JS/Emoji string-length weirdness 25 | const messageLength = function(message){ 26 | let total = 0; 27 | for(let word of message){ 28 | for(let char of word) total+=1; 29 | } 30 | return total; 31 | } 32 | 33 | const probabilities = function(message){ 34 | let result = {}, counts = frequency(message), totalChars = messageLength(message); 35 | for(let char of Object.keys(counts)){ 36 | const prob = (counts[char] / totalChars); 37 | result[char] = prob; 38 | } 39 | return result; 40 | } 41 | 42 | 43 | const surprises = function(message){ 44 | let result = {}, probability = probabilities(message); 45 | const chars = Object.keys(probability); 46 | 47 | for(let char of chars){ 48 | result[char] = Math.log2(1/probability[char]) 49 | } 50 | return result; 51 | } 52 | 53 | const entropy = function(message){ 54 | const surprise = Object.values(surprises(message)); 55 | const charCount = messageLength(message); 56 | const totalSurprise = surprise.reduce((total, s) => { 57 | return total + parseFloat(s) 58 | },0); 59 | return totalSurprise/charCount; 60 | } 61 | 62 | let message = "OMG!OMFG!! 🙄💩" 63 | let primer = `It was the best of times it was the worst of times it was the age of wisdom it was the age of foolishness it was the epoch of belief it was the epoch of incredulity it was the season of Light it was the season of Darkness it was the spring of hope it was the winter of despair we had everything before us we had nothing before us we were all going direct to Heaven we were all going direct the other way in short the period was so far like the present period that some of its noisiest authorities insisted on its being received for good or for evil in the superlative degree of comparison only There were a king with a large jaw and a queen with a plain face on the throne of England there were a king with a large jaw and a queen with a fair face on the throne of France In both countries it was clearer than crystal to the lords of the State preserves of loaves and fishes that things in general were settled for ever It was the year of Our Lord one thousand seven hundred and seventyfive Spiritual revelations were conceded to England at that favoured period as at this Mrs Southcott had recently attained her fiveandtwentieth blessed birthday of whom a prophetic private in the Life Guards had heralded the sublime appearance by announcing that arrangements were made for the swallowing up of London and Westminster Even the Cocklane ghost had been laid only a round dozen of years after rapping out its messages as the spirits of this very year last past supernaturally deficient in originality rapped out theirs Mere messages in the earthly order of events had lately come to the English Crown and People from a congress of British subjects in America which strange to relate have proved more important to the human race than any communications yet received through any of the chickens of the Cocklane brood France less favoured on the whole as to matters spiritual than her sister of the shield and trident rolled with exceeding smoothness down hill making paper money and spending it Under the guidance of her Christian pastors she entertained herself besides with such humane achievements as sentencing a youth to have his hands cut off his tongue torn out with pincers and his body burned alive because he had not kneeled down in the rain to do honour to a dirty procession of monks which passed within his view at a distance of some fifty or sixty yards It is likely enough that rooted in the woods of France and Norway there were growing trees when that sufferer was put to death already marked by the Woodman Fate to come down and be sawn into boards to make a certain movable framework with a sack and a knife in it terrible in history It is likely enough that in the rough outhouses of some tillers of the heavy lands adjacent to Paris there were sheltered from the weather that very day rude carts bespattered with rustic mire snuffed about by pigs and roosted in by poultry which the Farmer Death had already set apart to be his tumbrils of the Revolution But that Woodman and that Farmer though they work unceasingly work silently and no one heard them as they went about with muffled tread the rather forasmuch as to entertain any suspicion that they were awake was to be atheistical and traitorous In England there was scarcely an amount of order and protection to justify much national boasting Daring burglaries by armed men and highway robberies took place in the capital itself every night families were publicly cautioned not to go out of town without removing their furniture to upholsterers warehouses for security the highwayman in the dark was a City tradesman in the light and being recognised and challenged by his fellowtradesman whom he stopped in his character of the Captain gallantly shot him through the head and rode away the mail was waylaid by seven robbers and the guard shot three dead and then got shot dead himself by the other four in consequence of the failure of his ammunition after which the mail was robbed in peace that magnificent potentate the Lord Mayor of London was made to stand and deliver on Turnham Green by one highwayman who despoiled the illustrious creature in sight of all his retinue prisoners in London gaols fought battles with their turnkeys and the majesty of the law fired blunderbusses in among them loaded with rounds of shot and ball thieves snipped off diamond crosses from the necks of noble lords at Court drawingrooms musketeers went into St Giless to search for contraband goods and the mob fired on the musketeers and the musketeers fired on the mob and nobody thought any of these occurrences much out of the common way In the midst of them the hangman ever busy and ever worse than useless was in constant requisition now stringing up long rows of miscellaneous criminals now hanging a housebreaker on Saturday who had been taken on Tuesday now burning people in the hand at Newgate by the dozen and now burning pamphlets at the door of Westminster Hall today taking the life of an atrocious murderer and tomorrow of a wretched pilferer who had robbed a farmers boy of sixpence All these things and a thousand like them came to pass in and close upon the dear old year one thousand seven hundred and seventyfive Environed by them while the Woodman and the Farmer worked unheeded those two of the large jaws and those other two of the plain and the fair faces trod with stir enough and carried their divine rights with a high hand Thus did the year one thousand seven hundred and seventyfive conduct their Greatnesses and myriads of small creaturesthe creatures of this chronicle among the restalong the roads that lay before them`; 64 | 65 | const probs = probabilities(message); 66 | const sups = surprises(message) 67 | const freq = frequency(message); 68 | const ent = entropy(message); 69 | 70 | // console.log(freq); 71 | // console.log(probs); 72 | // console.log(sups); 73 | console.log(ent); 74 | 75 | const primerFrequency = frequency(primer.toUpperCase()); 76 | //console.log(primerFrequency); 77 | 78 | const Encoder = require("./encoder"); 79 | const encoder = new Encoder(); 80 | //console.log(encoder.encode(primer)); 81 | 82 | const checkMessage = `You want a toe? I can get you a toe, believe me. There are ways, Dude. You don't wanna know about it, believe me.` 83 | const encoded = encoder.encode(checkMessage); 84 | 85 | const errors = `010111011110011000001001010001100011000010000000110111101000110100000100000000110000010110101001100001011101111001100001000000011011110100010000010110001110110101011011010000101011010000011110010111100010000100111010100000100101000101111111000001011001100101101000010111011110011000001010111011000110000010010100011001100100000010110010110011100100100001101000000111100110011000110100110001000101011000111011010101101101000010101101` 86 | 87 | const decoded = encoder.decode(errors); 88 | //console.log(encoded); 89 | console.log(decoded); -------------------------------------------------------------------------------- /Season2/08-hashes/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "08-hashes", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "assert-options": { 8 | "version": "0.7.0", 9 | "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.7.0.tgz", 10 | "integrity": "sha512-7q9uNH/Dh8gFgpIIb9ja8PJEWA5AQy3xnBC8jtKs8K/gNVCr1K6kIvlm59HUyYgvM7oEDoLzGgPcGd9FqhtXEQ==" 11 | }, 12 | "bcryptjs": { 13 | "version": "2.4.3", 14 | "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", 15 | "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" 16 | }, 17 | "buffer-writer": { 18 | "version": "2.0.0", 19 | "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", 20 | "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" 21 | }, 22 | "inherits": { 23 | "version": "2.0.4", 24 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 25 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 26 | }, 27 | "packet-reader": { 28 | "version": "1.0.0", 29 | "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", 30 | "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" 31 | }, 32 | "pg": { 33 | "version": "8.5.1", 34 | "resolved": "https://registry.npmjs.org/pg/-/pg-8.5.1.tgz", 35 | "integrity": "sha512-9wm3yX9lCfjvA98ybCyw2pADUivyNWT/yIP4ZcDVpMN0og70BUWYEGXPCTAQdGTAqnytfRADb7NERrY1qxhIqw==", 36 | "requires": { 37 | "buffer-writer": "2.0.0", 38 | "packet-reader": "1.0.0", 39 | "pg-connection-string": "^2.4.0", 40 | "pg-pool": "^3.2.2", 41 | "pg-protocol": "^1.4.0", 42 | "pg-types": "^2.1.0", 43 | "pgpass": "1.x" 44 | } 45 | }, 46 | "pg-connection-string": { 47 | "version": "2.4.0", 48 | "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.4.0.tgz", 49 | "integrity": "sha512-3iBXuv7XKvxeMrIgym7njT+HlZkwZqqGX4Bu9cci8xHZNT+Um1gWKqCsAzcC0d95rcKMU5WBg6YRUcHyV0HZKQ==" 50 | }, 51 | "pg-cursor": { 52 | "version": "2.5.2", 53 | "resolved": "https://registry.npmjs.org/pg-cursor/-/pg-cursor-2.5.2.tgz", 54 | "integrity": "sha512-yS0lxXA5WoIVK7BUgJr1uOJDJe5JxVezItTLvqnTXj6bF3di4UtQOrPx8RW3GpFmom2NTQfpEc2N6vvdpopQSw==" 55 | }, 56 | "pg-int8": { 57 | "version": "1.0.1", 58 | "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", 59 | "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" 60 | }, 61 | "pg-minify": { 62 | "version": "1.6.2", 63 | "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.2.tgz", 64 | "integrity": "sha512-1KdmFGGTP6jplJoI8MfvRlfvMiyBivMRP7/ffh4a11RUFJ7kC2J0ZHlipoKiH/1hz+DVgceon9U2qbaHpPeyPg==" 65 | }, 66 | "pg-pool": { 67 | "version": "3.2.2", 68 | "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz", 69 | "integrity": "sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA==" 70 | }, 71 | "pg-promise": { 72 | "version": "10.8.6", 73 | "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-10.8.6.tgz", 74 | "integrity": "sha512-7Fiu4jBpRtbwsXtzfwwkVmEcde2yn1aSpIBnYLr2PRNHLwPxW9yyNN1ziBGJQ9nQ+IG67Wt1FF4KQNSFsg3i2g==", 75 | "requires": { 76 | "assert-options": "0.7.0", 77 | "pg": "8.5.1", 78 | "pg-minify": "1.6.2", 79 | "spex": "3.2.0" 80 | } 81 | }, 82 | "pg-protocol": { 83 | "version": "1.4.0", 84 | "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.4.0.tgz", 85 | "integrity": "sha512-El+aXWcwG/8wuFICMQjM5ZSAm6OWiJicFdNYo+VY3QP+8vI4SvLIWVe51PppTzMhikUJR+PsyIFKqfdXPz/yxA==" 86 | }, 87 | "pg-query-stream": { 88 | "version": "4.0.0", 89 | "resolved": "https://registry.npmjs.org/pg-query-stream/-/pg-query-stream-4.0.0.tgz", 90 | "integrity": "sha512-Jftit2EUBn+ilh4JtAgw0JXKR54vATmYHlZ4fmIlbZgL1qT/GKUuwMzLFT8QQm+qJHZwlRIIfkMUOP7soY38ag==", 91 | "requires": { 92 | "pg-cursor": "^2.5.2" 93 | } 94 | }, 95 | "pg-types": { 96 | "version": "2.2.0", 97 | "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", 98 | "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", 99 | "requires": { 100 | "pg-int8": "1.0.1", 101 | "postgres-array": "~2.0.0", 102 | "postgres-bytea": "~1.0.0", 103 | "postgres-date": "~1.0.4", 104 | "postgres-interval": "^1.1.0" 105 | } 106 | }, 107 | "pgpass": { 108 | "version": "1.0.4", 109 | "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz", 110 | "integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==", 111 | "requires": { 112 | "split2": "^3.1.1" 113 | } 114 | }, 115 | "postgres-array": { 116 | "version": "2.0.0", 117 | "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", 118 | "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" 119 | }, 120 | "postgres-bytea": { 121 | "version": "1.0.0", 122 | "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", 123 | "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" 124 | }, 125 | "postgres-date": { 126 | "version": "1.0.7", 127 | "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", 128 | "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" 129 | }, 130 | "postgres-interval": { 131 | "version": "1.2.0", 132 | "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", 133 | "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", 134 | "requires": { 135 | "xtend": "^4.0.0" 136 | } 137 | }, 138 | "readable-stream": { 139 | "version": "3.6.0", 140 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 141 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 142 | "requires": { 143 | "inherits": "^2.0.3", 144 | "string_decoder": "^1.1.1", 145 | "util-deprecate": "^1.0.1" 146 | } 147 | }, 148 | "safe-buffer": { 149 | "version": "5.2.1", 150 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 151 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 152 | }, 153 | "scrypt-js": { 154 | "version": "3.0.1", 155 | "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", 156 | "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" 157 | }, 158 | "spex": { 159 | "version": "3.2.0", 160 | "resolved": "https://registry.npmjs.org/spex/-/spex-3.2.0.tgz", 161 | "integrity": "sha512-9srjJM7NaymrpwMHvSmpDeIK5GoRMX/Tq0E8aOlDPS54dDnDUIp30DrP9SphMPEETDLzEM9+4qo+KipmbtPecg==" 162 | }, 163 | "split2": { 164 | "version": "3.2.2", 165 | "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", 166 | "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", 167 | "requires": { 168 | "readable-stream": "^3.0.0" 169 | } 170 | }, 171 | "string_decoder": { 172 | "version": "1.3.0", 173 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 174 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 175 | "requires": { 176 | "safe-buffer": "~5.2.0" 177 | } 178 | }, 179 | "util-deprecate": { 180 | "version": "1.0.2", 181 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 182 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 183 | }, 184 | "xtend": { 185 | "version": "4.0.2", 186 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 187 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /Season2/07-encryption/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "07-encryption", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@ungap/promise-all-settled": { 8 | "version": "1.1.2", 9 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", 10 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==" 11 | }, 12 | "ansi-colors": { 13 | "version": "4.1.1", 14 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 15 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" 16 | }, 17 | "ansi-regex": { 18 | "version": "3.0.0", 19 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 20 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" 21 | }, 22 | "ansi-styles": { 23 | "version": "4.3.0", 24 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 25 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 26 | "requires": { 27 | "color-convert": "^2.0.1" 28 | } 29 | }, 30 | "anymatch": { 31 | "version": "3.1.1", 32 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", 33 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", 34 | "requires": { 35 | "normalize-path": "^3.0.0", 36 | "picomatch": "^2.0.4" 37 | } 38 | }, 39 | "argparse": { 40 | "version": "1.0.10", 41 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 42 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 43 | "requires": { 44 | "sprintf-js": "~1.0.2" 45 | } 46 | }, 47 | "balanced-match": { 48 | "version": "1.0.0", 49 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 50 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 51 | }, 52 | "binary-extensions": { 53 | "version": "2.1.0", 54 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", 55 | "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==" 56 | }, 57 | "brace-expansion": { 58 | "version": "1.1.11", 59 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 60 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 61 | "requires": { 62 | "balanced-match": "^1.0.0", 63 | "concat-map": "0.0.1" 64 | } 65 | }, 66 | "braces": { 67 | "version": "3.0.2", 68 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 69 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 70 | "requires": { 71 | "fill-range": "^7.0.1" 72 | } 73 | }, 74 | "browser-stdout": { 75 | "version": "1.3.1", 76 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 77 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" 78 | }, 79 | "camelcase": { 80 | "version": "5.3.1", 81 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 82 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" 83 | }, 84 | "chalk": { 85 | "version": "4.1.0", 86 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 87 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 88 | "requires": { 89 | "ansi-styles": "^4.1.0", 90 | "supports-color": "^7.1.0" 91 | } 92 | }, 93 | "chokidar": { 94 | "version": "3.4.3", 95 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", 96 | "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", 97 | "requires": { 98 | "anymatch": "~3.1.1", 99 | "braces": "~3.0.2", 100 | "fsevents": "~2.1.2", 101 | "glob-parent": "~5.1.0", 102 | "is-binary-path": "~2.1.0", 103 | "is-glob": "~4.0.1", 104 | "normalize-path": "~3.0.0", 105 | "readdirp": "~3.5.0" 106 | } 107 | }, 108 | "cliui": { 109 | "version": "5.0.0", 110 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 111 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 112 | "requires": { 113 | "string-width": "^3.1.0", 114 | "strip-ansi": "^5.2.0", 115 | "wrap-ansi": "^5.1.0" 116 | }, 117 | "dependencies": { 118 | "ansi-regex": { 119 | "version": "4.1.0", 120 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 121 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" 122 | }, 123 | "string-width": { 124 | "version": "3.1.0", 125 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 126 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 127 | "requires": { 128 | "emoji-regex": "^7.0.1", 129 | "is-fullwidth-code-point": "^2.0.0", 130 | "strip-ansi": "^5.1.0" 131 | } 132 | }, 133 | "strip-ansi": { 134 | "version": "5.2.0", 135 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 136 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 137 | "requires": { 138 | "ansi-regex": "^4.1.0" 139 | } 140 | } 141 | } 142 | }, 143 | "color-convert": { 144 | "version": "2.0.1", 145 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 146 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 147 | "requires": { 148 | "color-name": "~1.1.4" 149 | } 150 | }, 151 | "color-name": { 152 | "version": "1.1.4", 153 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 154 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 155 | }, 156 | "concat-map": { 157 | "version": "0.0.1", 158 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 159 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 160 | }, 161 | "debug": { 162 | "version": "4.2.0", 163 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", 164 | "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", 165 | "requires": { 166 | "ms": "2.1.2" 167 | } 168 | }, 169 | "decamelize": { 170 | "version": "1.2.0", 171 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 172 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 173 | }, 174 | "diff": { 175 | "version": "4.0.2", 176 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 177 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" 178 | }, 179 | "emoji-regex": { 180 | "version": "7.0.3", 181 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 182 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" 183 | }, 184 | "escape-string-regexp": { 185 | "version": "4.0.0", 186 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 187 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" 188 | }, 189 | "esprima": { 190 | "version": "4.0.1", 191 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 192 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" 193 | }, 194 | "fill-range": { 195 | "version": "7.0.1", 196 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 197 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 198 | "requires": { 199 | "to-regex-range": "^5.0.1" 200 | } 201 | }, 202 | "find-up": { 203 | "version": "5.0.0", 204 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 205 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 206 | "requires": { 207 | "locate-path": "^6.0.0", 208 | "path-exists": "^4.0.0" 209 | } 210 | }, 211 | "flat": { 212 | "version": "5.0.2", 213 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 214 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==" 215 | }, 216 | "fs.realpath": { 217 | "version": "1.0.0", 218 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 219 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 220 | }, 221 | "fsevents": { 222 | "version": "2.1.3", 223 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", 224 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", 225 | "optional": true 226 | }, 227 | "get-caller-file": { 228 | "version": "2.0.5", 229 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 230 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" 231 | }, 232 | "glob": { 233 | "version": "7.1.6", 234 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 235 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 236 | "requires": { 237 | "fs.realpath": "^1.0.0", 238 | "inflight": "^1.0.4", 239 | "inherits": "2", 240 | "minimatch": "^3.0.4", 241 | "once": "^1.3.0", 242 | "path-is-absolute": "^1.0.0" 243 | } 244 | }, 245 | "glob-parent": { 246 | "version": "5.1.1", 247 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 248 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 249 | "requires": { 250 | "is-glob": "^4.0.1" 251 | } 252 | }, 253 | "growl": { 254 | "version": "1.10.5", 255 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 256 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" 257 | }, 258 | "has-flag": { 259 | "version": "4.0.0", 260 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 261 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" 262 | }, 263 | "he": { 264 | "version": "1.2.0", 265 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 266 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" 267 | }, 268 | "inflight": { 269 | "version": "1.0.6", 270 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 271 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 272 | "requires": { 273 | "once": "^1.3.0", 274 | "wrappy": "1" 275 | } 276 | }, 277 | "inherits": { 278 | "version": "2.0.4", 279 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 280 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 281 | }, 282 | "is-binary-path": { 283 | "version": "2.1.0", 284 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 285 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 286 | "requires": { 287 | "binary-extensions": "^2.0.0" 288 | } 289 | }, 290 | "is-extglob": { 291 | "version": "2.1.1", 292 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 293 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" 294 | }, 295 | "is-fullwidth-code-point": { 296 | "version": "2.0.0", 297 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 298 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" 299 | }, 300 | "is-glob": { 301 | "version": "4.0.1", 302 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 303 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 304 | "requires": { 305 | "is-extglob": "^2.1.1" 306 | } 307 | }, 308 | "is-number": { 309 | "version": "7.0.0", 310 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 311 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" 312 | }, 313 | "is-plain-obj": { 314 | "version": "2.1.0", 315 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 316 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" 317 | }, 318 | "isexe": { 319 | "version": "2.0.0", 320 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 321 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 322 | }, 323 | "js-yaml": { 324 | "version": "3.14.0", 325 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", 326 | "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", 327 | "requires": { 328 | "argparse": "^1.0.7", 329 | "esprima": "^4.0.0" 330 | } 331 | }, 332 | "locate-path": { 333 | "version": "6.0.0", 334 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 335 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 336 | "requires": { 337 | "p-locate": "^5.0.0" 338 | } 339 | }, 340 | "log-symbols": { 341 | "version": "4.0.0", 342 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", 343 | "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", 344 | "requires": { 345 | "chalk": "^4.0.0" 346 | } 347 | }, 348 | "minimatch": { 349 | "version": "3.0.4", 350 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 351 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 352 | "requires": { 353 | "brace-expansion": "^1.1.7" 354 | } 355 | }, 356 | "mocha": { 357 | "version": "8.2.1", 358 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.1.tgz", 359 | "integrity": "sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w==", 360 | "requires": { 361 | "@ungap/promise-all-settled": "1.1.2", 362 | "ansi-colors": "4.1.1", 363 | "browser-stdout": "1.3.1", 364 | "chokidar": "3.4.3", 365 | "debug": "4.2.0", 366 | "diff": "4.0.2", 367 | "escape-string-regexp": "4.0.0", 368 | "find-up": "5.0.0", 369 | "glob": "7.1.6", 370 | "growl": "1.10.5", 371 | "he": "1.2.0", 372 | "js-yaml": "3.14.0", 373 | "log-symbols": "4.0.0", 374 | "minimatch": "3.0.4", 375 | "ms": "2.1.2", 376 | "nanoid": "3.1.12", 377 | "serialize-javascript": "5.0.1", 378 | "strip-json-comments": "3.1.1", 379 | "supports-color": "7.2.0", 380 | "which": "2.0.2", 381 | "wide-align": "1.1.3", 382 | "workerpool": "6.0.2", 383 | "yargs": "13.3.2", 384 | "yargs-parser": "13.1.2", 385 | "yargs-unparser": "2.0.0" 386 | } 387 | }, 388 | "ms": { 389 | "version": "2.1.2", 390 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 391 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 392 | }, 393 | "nanoid": { 394 | "version": "3.1.12", 395 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", 396 | "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==" 397 | }, 398 | "normalize-path": { 399 | "version": "3.0.0", 400 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 401 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" 402 | }, 403 | "once": { 404 | "version": "1.4.0", 405 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 406 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 407 | "requires": { 408 | "wrappy": "1" 409 | } 410 | }, 411 | "p-limit": { 412 | "version": "3.0.2", 413 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", 414 | "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", 415 | "requires": { 416 | "p-try": "^2.0.0" 417 | } 418 | }, 419 | "p-locate": { 420 | "version": "5.0.0", 421 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 422 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 423 | "requires": { 424 | "p-limit": "^3.0.2" 425 | } 426 | }, 427 | "p-try": { 428 | "version": "2.2.0", 429 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 430 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" 431 | }, 432 | "path-exists": { 433 | "version": "4.0.0", 434 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 435 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" 436 | }, 437 | "path-is-absolute": { 438 | "version": "1.0.1", 439 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 440 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 441 | }, 442 | "picomatch": { 443 | "version": "2.2.2", 444 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 445 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" 446 | }, 447 | "randombytes": { 448 | "version": "2.1.0", 449 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 450 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 451 | "requires": { 452 | "safe-buffer": "^5.1.0" 453 | } 454 | }, 455 | "readdirp": { 456 | "version": "3.5.0", 457 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", 458 | "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", 459 | "requires": { 460 | "picomatch": "^2.2.1" 461 | } 462 | }, 463 | "require-directory": { 464 | "version": "2.1.1", 465 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 466 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" 467 | }, 468 | "require-main-filename": { 469 | "version": "2.0.0", 470 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 471 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" 472 | }, 473 | "safe-buffer": { 474 | "version": "5.2.1", 475 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 476 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 477 | }, 478 | "serialize-javascript": { 479 | "version": "5.0.1", 480 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", 481 | "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", 482 | "requires": { 483 | "randombytes": "^2.1.0" 484 | } 485 | }, 486 | "set-blocking": { 487 | "version": "2.0.0", 488 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 489 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" 490 | }, 491 | "sprintf-js": { 492 | "version": "1.0.3", 493 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 494 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" 495 | }, 496 | "string-width": { 497 | "version": "2.1.1", 498 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 499 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 500 | "requires": { 501 | "is-fullwidth-code-point": "^2.0.0", 502 | "strip-ansi": "^4.0.0" 503 | } 504 | }, 505 | "strip-ansi": { 506 | "version": "4.0.0", 507 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 508 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 509 | "requires": { 510 | "ansi-regex": "^3.0.0" 511 | } 512 | }, 513 | "strip-json-comments": { 514 | "version": "3.1.1", 515 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 516 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" 517 | }, 518 | "supports-color": { 519 | "version": "7.2.0", 520 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 521 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 522 | "requires": { 523 | "has-flag": "^4.0.0" 524 | } 525 | }, 526 | "to-regex-range": { 527 | "version": "5.0.1", 528 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 529 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 530 | "requires": { 531 | "is-number": "^7.0.0" 532 | } 533 | }, 534 | "vigenere": { 535 | "version": "1.0.2", 536 | "resolved": "https://registry.npmjs.org/vigenere/-/vigenere-1.0.2.tgz", 537 | "integrity": "sha1-b2jmSuAZCQoSZEY7XS8ZzgcNo+E=" 538 | }, 539 | "which": { 540 | "version": "2.0.2", 541 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 542 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 543 | "requires": { 544 | "isexe": "^2.0.0" 545 | } 546 | }, 547 | "which-module": { 548 | "version": "2.0.0", 549 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 550 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" 551 | }, 552 | "wide-align": { 553 | "version": "1.1.3", 554 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 555 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 556 | "requires": { 557 | "string-width": "^1.0.2 || 2" 558 | } 559 | }, 560 | "workerpool": { 561 | "version": "6.0.2", 562 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", 563 | "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==" 564 | }, 565 | "wrap-ansi": { 566 | "version": "5.1.0", 567 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 568 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 569 | "requires": { 570 | "ansi-styles": "^3.2.0", 571 | "string-width": "^3.0.0", 572 | "strip-ansi": "^5.0.0" 573 | }, 574 | "dependencies": { 575 | "ansi-regex": { 576 | "version": "4.1.0", 577 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 578 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" 579 | }, 580 | "ansi-styles": { 581 | "version": "3.2.1", 582 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 583 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 584 | "requires": { 585 | "color-convert": "^1.9.0" 586 | } 587 | }, 588 | "color-convert": { 589 | "version": "1.9.3", 590 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 591 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 592 | "requires": { 593 | "color-name": "1.1.3" 594 | } 595 | }, 596 | "color-name": { 597 | "version": "1.1.3", 598 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 599 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 600 | }, 601 | "string-width": { 602 | "version": "3.1.0", 603 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 604 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 605 | "requires": { 606 | "emoji-regex": "^7.0.1", 607 | "is-fullwidth-code-point": "^2.0.0", 608 | "strip-ansi": "^5.1.0" 609 | } 610 | }, 611 | "strip-ansi": { 612 | "version": "5.2.0", 613 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 614 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 615 | "requires": { 616 | "ansi-regex": "^4.1.0" 617 | } 618 | } 619 | } 620 | }, 621 | "wrappy": { 622 | "version": "1.0.2", 623 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 624 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 625 | }, 626 | "y18n": { 627 | "version": "4.0.0", 628 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", 629 | "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" 630 | }, 631 | "yargs": { 632 | "version": "13.3.2", 633 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", 634 | "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", 635 | "requires": { 636 | "cliui": "^5.0.0", 637 | "find-up": "^3.0.0", 638 | "get-caller-file": "^2.0.1", 639 | "require-directory": "^2.1.1", 640 | "require-main-filename": "^2.0.0", 641 | "set-blocking": "^2.0.0", 642 | "string-width": "^3.0.0", 643 | "which-module": "^2.0.0", 644 | "y18n": "^4.0.0", 645 | "yargs-parser": "^13.1.2" 646 | }, 647 | "dependencies": { 648 | "ansi-regex": { 649 | "version": "4.1.0", 650 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 651 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" 652 | }, 653 | "find-up": { 654 | "version": "3.0.0", 655 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 656 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 657 | "requires": { 658 | "locate-path": "^3.0.0" 659 | } 660 | }, 661 | "locate-path": { 662 | "version": "3.0.0", 663 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 664 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 665 | "requires": { 666 | "p-locate": "^3.0.0", 667 | "path-exists": "^3.0.0" 668 | } 669 | }, 670 | "p-limit": { 671 | "version": "2.3.0", 672 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 673 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 674 | "requires": { 675 | "p-try": "^2.0.0" 676 | } 677 | }, 678 | "p-locate": { 679 | "version": "3.0.0", 680 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 681 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 682 | "requires": { 683 | "p-limit": "^2.0.0" 684 | } 685 | }, 686 | "path-exists": { 687 | "version": "3.0.0", 688 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 689 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" 690 | }, 691 | "string-width": { 692 | "version": "3.1.0", 693 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 694 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 695 | "requires": { 696 | "emoji-regex": "^7.0.1", 697 | "is-fullwidth-code-point": "^2.0.0", 698 | "strip-ansi": "^5.1.0" 699 | } 700 | }, 701 | "strip-ansi": { 702 | "version": "5.2.0", 703 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 704 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 705 | "requires": { 706 | "ansi-regex": "^4.1.0" 707 | } 708 | } 709 | } 710 | }, 711 | "yargs-parser": { 712 | "version": "13.1.2", 713 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 714 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 715 | "requires": { 716 | "camelcase": "^5.0.0", 717 | "decamelize": "^1.2.0" 718 | } 719 | }, 720 | "yargs-unparser": { 721 | "version": "2.0.0", 722 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 723 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 724 | "requires": { 725 | "camelcase": "^6.0.0", 726 | "decamelize": "^4.0.0", 727 | "flat": "^5.0.2", 728 | "is-plain-obj": "^2.1.0" 729 | }, 730 | "dependencies": { 731 | "camelcase": { 732 | "version": "6.2.0", 733 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", 734 | "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==" 735 | }, 736 | "decamelize": { 737 | "version": "4.0.0", 738 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 739 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==" 740 | } 741 | } 742 | } 743 | } 744 | } 745 | --------------------------------------------------------------------------------