text:
# basic.30.types

## General

1. Simple (or primitive) value types are
    * numbers
    * strings
    * boolean
    * undefined
    * null

1. All other values are objects
    * Arrays are objects
    * Functions are objects
    * Regular Expressions are objects
    * Objects are objects

## Bonus

## JavaScript falsy Values

1. false
1. 0
1. ""
1. null
1. undefined
1. NaN

## Javascript types -> These are  values produced by typeof operator
1. number
1. string
1. boolean
1. undefined
1. function
1. object

## JavaScript built in values
1. true
1. false
1. null
1. undefined
1. NaN
1. Infinity

# basic.30.operators.arithmetic

## Infix Operators

### add +
  1. Number + Number = addition
  1. Boolean + Number = addition
  1. Boolean + Boolean = addition
  1. String + Number  = concatenation
```
var x = "foo" + 1 // x value = foo1 , type = string
var x = "4" + 1   // x value = 41 , x type = string
```
  1. String + Boolean = concatenation
  1. String + String = concatenation

### subtract -
  1. Number - Number = subctraction
  1. "100" - Number  = subtraction // Numbers enclosed in quotes are  converted into numbers
  1. Number - Boolean = subtraction //Boolean values are converted to numbers
  1. Boolean - Boolean = subtraction
  1. String - String = NaN
  1. String - Number  = NaN

### multiply *
  1. Infinity * 0 = NaN
  1. Infinity * Infinity = Infinity
  1. Infinity * -Infinity = -Infinity
  1. Number * -0 = -0
  1. "2" * Number  = multiplication // Numbers enclosed in quotes are converted to numbers
  1. Boolean * Number = multiplication // Boolean converted to a number
  1. String * Number = NaN
  1. String * String = NaN

### divide /
  1. Number / 0 = Infinity
  1. Number / -0 = -Infinity
  1. Boolean / Number = division // Boolean converted to a number
  1. "4" / Number  = division // Numbers enclosed in quotes are converted to numbers
  1. String / Number = NaN
  1. String / String = NaN

### Remainder %
```
-5 % 2  = -1 // remainder operator takes the sign of the numerator (or dividend)
5 % -2  = 1  // remainder operator takes the sign of the numerator (or dividend)
"5" % 2 = 1  // Numbers enclosed in quotes are converted to number type
```
### postfix increment x++ , prefix increment ++x
  1. Postfix ++ will return the value of operand before incrementing it. Prefix ++ will increment the value of operand before returning it
```
var x = 1;
var y = x++;
console.log (y); // y will be 1 . Postfix ++ will return the value of x before incrementing
```
```
var x = 1;
var y = ++x;
console.log (y); // y will be 2 . Prefix ++ will increment the value of x before returning it
```
  1. Increment operator does not concatenate strings like the addition + operator
```
var x= "4" ;
var y= ++x ;
console.log(y); // y value will be 5 and type number (not 41 and type string).
```
```
var x= "4";
var y= x++;
console.log(y); // y value will be 4 and type number (not 41 and type string).
```
  1. ++ operator will convert numbers enclosed in quotes (string values) into number values
```
var x = "4";
x++;  // x will have a value of 5 and type number
```
### postfix decrement x-- , prefix decrement --x
```
var x = 2;
var y = x--;
console.log (y); // y will be 2 . Postfix -- will return the value of x before decrementing
```
```
var x = 2;
var y = --x;
console.log (y)  // y will be 1 . Prefix -- will decrement the value of x before returning it
```
### unary -
  1. unary - attempts to convert its operand into a number type.
```
var v = -"1" ; // v value will be -1 and type will be  number
```
### unary plus or tonumber  +
  1. unary + attempts to convert its operand into a number type.

# basic.30.operators.logical

## JavaScript Falsy Values

  1. false
  1. 0
  1. ""
  1. null
  1. undefined
  1. NaN

## Logical And (&&)

  1. expr1 && expr2 -> Takes two operands
  1. Returns expr1 if expr1 is falsy else returns expr2

## Logical Or (||)

  1. expr1 || expr2 -> Takes two operands
  1. Returns expr2 if expr1 is falsy else returns expr1

## Conditional Operator (Also known as ternary operator)

  1. condition ? expr1 : expr2 -> Takes three operands operand 1 = condition , operand 2 = expr1 and operand 3 = expr2
  1. Returns expr2 if value of condition is falsy else retrun expr1

## Logical NOT (!)

  1. Logical NOT operator takes one operand
  1. ! expr1
  1. returns true if expr1 is falsy else returns false

# basic.30.expressions.functions

## Function Literal

  1. A function literal is an expression that defines a value of type function . Another way of defining a function

```
var myFunction = function(x){
x = x * x;
return x;
}

```

  1. It can have an optional name. Function with no name are called anonymous functions
  1. It can specify a list of parameters enclosed in braces (...)  // (x)
  1. The body of function enclosed in curly braces {...}
  1. The function returns a value with a return statement.
  1. If a function does not return a value with a return statement then undefined is returned when the function exits
  1. typeof myFunction = function
  1. function parameters are specified when a function is declared. In the example above x is a function parameter.
  1. function arguments are passed to functions when the function is invoked. In the examle below 5 is function argument
      var y = myFunction(5);

## Function objects

  1. Functions in Javascript are Objects
  1. Objects are collections of name/value pairs with a hidden link to prototype object
  1. Objects produced from Object literals are linked to Object.prototype
  1. functions can be used like any other value since they are objects
  1. functions can be stored in variables , objects and arrays
  1. Functions can be passed as arguments to functions
  1. functions can be returned from functions
  1. functions can have methods

# basic.30.control.structures

## References

  1. [typeof Operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof)
  1. [isFinite function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite)
  1. [isNaN function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isNaN)
  1. [if...else statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#if...else_statement)
  1. [for Statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration#for_statement)
  1. [break Statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break)
  1. [Control flow and error handling](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling)

## Throwing Errors
1. Use throw statement to generte an exception from your function
1. Exceptions can be generated using string values
```
// incremento
let incremento = function (x){
if (typeof(x) !== 'number'){
  throw  "x is not a number";  // throw an exception with a string
}

if (isNaN(x)){
throw  'x is a NaN';           // throw an exception with a string
}

if (!isFinite(x)){
  throw  'x is not Finite';    // throw an error object using new
}

++x;
return x;

}                              // end of incremento

```

# basic.30.strings

## General

1. A string literal can be wrapped in single quotes or double quotes

```
var str = "Hello";
var anotherStr = 'World';
```
1. Use typeof operator to find if a value is of type string

```
typeof (str) === "string" //returns true
```

1. A string contains zero or more characters. Each character is 16 bits wide

## length property
1. String literals have a length property

```
"Hello".length ;  // returns 5
```

1. Use toString() method to convert a value to a string

```
true.toString()    // returns "true"
100.toString()     // returns "100";
[1,2,3].toString() // retunrs "1,2,3";

```
1. Use parseInt() method to convert a string to a number
  1. pasrseInt takes 2 parameters string to convert and radix.  Use charAt method to retrieve characters from the string

```
var str = "Hello";
var firstChar = str.charAt(0) // returns "H"
var secondChar = str.charAt(1)  // returns "e"
var fifthChar = str.charAt(4) // returns "d"
var sixthChar = str.charAt(5) // returns "" empty string
```

1. loop thorugh all characters in a string using for loop

```
var i;
for(i=0 ; i < str.length ; i++) {
console.log(str.charAt(i));
}
```

## concatenating  strings

1. use the + operator to concatenate strings

```
var str = "Jean";
console.log( str.length)   // prints 4
str = str + " " + "Genie";
console.log (str);         // prints 'Jean Genie'
console.log (str.length);  // prints  10
```
## split method

The split() method splits a String object into an array of strings

1. Split a string by Space " "

```
var  str, result;
str =  "221 B Baker St, London, England"
result  = str.split(" ");
console.log (result);                    // will print [ '221', 'B', 'Baker', 'St,', 'London,', 'England' ]
console.log (result[0])                  // will print 221
console.log (result[1])                  // will print B
```
1. Split a string by each character

```
var  str, result;
str =  "Moonage Daydream"
result  = str.split("");
console.log (result);     // will print [ 'M','o','o','n','a','g','e',' ','D','a','y','d','r','e','a','m' ]
console.log (result[0])   // will print M
console.log (result[1])   // will print o
```

1. Split a string by  colons :

```
var  str, result;
str =  "Houston:We:Have:A:Problem";
result  = str.split(":");
console.log (result);               // will print [ 'Houston', 'We', 'Have', 'A', 'Problem' ]
console.log (result[0])             // will print Houston
console.log (result[1])             // will print We
```

## slice method
1. The string.slice(start, end ) method extracts a section of a string and returns a new string.

```
var  str, result;
str =  "221 B Baker St, London, England"
console.log (str.slice(0,3));            // prints 221
console.log(str.slice(6,6+5));           // prints Baker
console.log(str.slice(6));               // prints Baker St, London, England
```

## strings.indexOf

1. Returns the index of the first occurrence of the specified value, Returns -1 if the value is not found.

```
var  str, result;
str =  "221 B Baker St, London, England"
console.log (str.indexOf("Baker"));       // prints 6
console.log (str.indexOf("Tokyo"));       // prints -1
```

## replace(searchValue, replaceValue)
1. Returns the index of the first occurrence of the specified value, Returns -1 if the value is not found.
1. searchValue can be a string or a regular expression, repalceValue is a string

```
var  str, result;
str =  "221 B Baker St, London, England"
console.log (str.replace("221", "5050"); // prints  "5050 B Baker St, Tokyo, England"
```
1. If searchValue is a string then only first occurance of is replaced

```
var  str, result;
str =  "221 B Baker St, London, England"
console.log (str.replace(" ", "-"));      //prints '221-B Baker St, London, England'
```

##  Escape Notation and  White spaces
1. Escape character is used to inserting characters into strings that are normally not permitted such as quotes
1.  \ (backslash) is the  escape character

```
var str = 'Ceaser is my father\'s sister\'s son\'s dog'; // use \ to escape single quote
console.log (str)                                        // prints 'Ceaser is my father's sister's son's dog'

```

1. White spaces in Javascript are
  1. space = " "
  1. tab = "\t"
  1. End of Line = "\n" and
  1. Carriage Return = "\r"

```
// Function to check if a string has a whiteSpace
// Returns true is parameter has a white space, false otherwise

function hasWhiteSpace(str){
  var i, returnValue;
  returnValue = false;
  for (i=0 ; i < str.length ; i++){
  var char = str.charAt(i);
  if (char === " " || char === "\t" || char === "\n" || char === "\r"){
    returnValue = true;

  }                                                                     // end of if

  }                                                                     // end of for loop

  return returnValue;

}                                                                       // end of hasWhiteSpace

console.log (hasWhiteSpace("starman"));                                 // prints false
console.log (hasWhiteSpace("Jean Genie"));                              // prints true
console.log (hasWhiteSpace("Jean" + "\t" + "Genie"));                   // prints true
```

# basic.30.arrays

## General

1. An array literal is a pair of square brackets surrounding zero or more values separated by commas

```
var fruits =["Apple", "Kiwi"]
```

1. The first value will get a property name '0' , second value will get a property name '1'
1. typeof (fruits) === "object"
1. To check if a value is of Array type, use Array.isArray() method

```
Array.isArray(fruits) // returns true
```

## length property
1. Arrays have a length property

```
var fruits =["Apple", "Kiwi"]
console.log(fruits.length) // = 2
```

1. The length property is not necessarily the number of values in the array

```
var veggies = [];
veggies[100]= "Potatos";
console.log (veggies.length) // wiil print 101 but there is only one value in the array
```

## Access & Enumeration

1. Access Array Element using numbers enclosed in square brackets staring with zero

```
var fruits =["Apple", "Kiwi"]
var firstFruit = fruits[0];   // fristFruit will have a value =  "Apple"
var secondFruit = fruits[1];  // secondFruit will have a value = "Kiwi"
var thridFruit = fruits[2];   // thirdFruit will have a value = undefined
```

1. Loop through all elements of array using for loop

```
var fruits =["Apple", "Kiwi"]
var i;
for(i=0; i < fruits.length ; i++){
console.log (fruits[i]);
}
```

## Adding Values to Arrays
1. Adding values to Arrays

```
var fruits =["Apple", "Kiwi"]
fruits[2] = "Banana"
console.log (fruits.length)   // will print 3 ,
console.log (fruits)          // ["Apple", "Kiwi", "Banana"]

```

1. Add value to the end of an Array push method

```
var fruits =["Apple", "Kiwi", "Banana"];
var totalFruits = fruits.push("Orange", "Mango");
console.log (fruits)                              // frutis = ["Apple", "Kiwi", "Banana", "Orange" , "Mango"]
cosnole.log (totalFruits)                         // totalFruits = 5
```

1. Add value to the beginning of an Array unshift  method

```
var fruits = ["Apple", "Kiwi", "Banana", "Orange" , "Mango"]
var totalFruits = fruits.unshift("Grape Fruit","Grape");
console.log (fruits)                                         // ["Grape Fruit","Grape","Apple", "Kiwi", "Banana", "Orange" , "Mango"]
cosnole.log (totalFruits)                                    // totalFruits = 7
```

## Removing Values from Arrays

1. Remove last value of an Array use  pop method

```
var fruits = ["Apple", "Kiwi", "Banana", "Orange" , "Mango"];
var lastFruit = fruits.pop();
console.log (fruits);                                         // frutis = ["Apple", "Kiwi", "Banana","Orange"];
cosnole.log (lastFruit);                                      // lastFruit = "Mango"
```

1. shift method, remove first element of an array

```
var fruits = ["Apple", "Kiwi", "Banana", "Orange" , "Mango"];
var firstFruit = fruits.shift();
console.log (fruits);                                         // frutis = ["Kiwi", "Banana","Orange","Mango"];
cosnole.log (firstFruit);                                     // firstFruit = "Apple"
```

## Finding values in arrays

1. Use includes() method to find if an array includes a certain value

```
var vowels , char1 , char2;
vowels = ["a", "e", "i", "o" , "u" , "A", "E" , "I" , "O", "U"];
char1 = "i"; char2 = "p";
console.log (vowels.includes(char1) )                            // prints true;
console.log (vowels.includes(char2) )                            // prints false;
```
1. Use indexOf() method to find the index of a value in an array
  1. returns the first index of the value in the array; -1 if not found.

```
var whiteSpaces , char1 , char2;
whiteSpaces = [" ","/t","n", "/r"];
char1 = "The Jean Genie".charAt(3)        // char1 = " "
char2 = "The Jean Genie".charAt(4)        // char2 = "J"
console.log (whiteSpaces.indexOf(char1) ) // prints 0;
console.log (whiteSpaces.indexOf(char2) ) // prints -1;
```

## misc
1. Arrays are passed around by reference

```
var sushi = ["maki" , "sahsimi"]; // sushi points to a location in memory that holds array object with "maki" and "sashimi" values
var pizza = sushi;                // pizza now points to the same location in memory that holds array object with "maki" and "sashimi" values
console.log( pizza[1]) ;          // prints 'sashimi'
pizza.push("chicago");            // adds "chicago" to the array object that previosuly had 2 values "maki" and "sashimi"
console.log(sushi.length);        // prints 3;
console.log (sushi[2]);           // prints 'chicago'

```

1. Arrays are passed to functions by reference.

```
var sushi , pizzas ;
sushi =  ["nigri" , "sashimi" , "maki"]; // sushi points to an array object with 3 values

// Declare a function addPizza that takes array as input parameter

var addPizza = function(someArray){
  someArray.push("chicago");
}
addPizza(sushi); // Invoke addPizza  with sushi as arguement.
//sushi is passed to addPizza function by reference.
//This means that that someArray parameter of function addPizza points to the same array object that sushi points to
// addPizza executes and adds a value "chicago" to the same array object that sushi points to

console.log (sushi); // this will print ["nigri", "sashimi" , "maki","chicago"];

```

1. Copying Arrays, Use  spread (...) syntax to make a copy of an array

```
var coffee = ["espresso" , "cappuccino"];
var moreCoffee = [...coffee];
console.log (moreCoffee)          // prints ['expresso','cappuccino']
moreCoffee.push ("latte");
console.log (moreCoffee);         // prints ['expresso','cappuccino','latte']
console.log (coffee)              // prints ['expresso','cappuccino']
```

# basic.30.scope
  1. Variables in JS have 3 types of scope: global , function and block (with ES6)
  1. Variables with block scope are visible anywhere in the block. Not visible outside the block
  1. Variables with function scope are visible anywhere in the function. Not visible outside the function
  1. Variables with global scope are visible(accessible) anywhere in the program
  1. Inner blocks get access to parameters and variables of the blocks that they are defiend within
  1. Basic.60.scope ->Inner blocks do not get access to arguments this
  1. Basic.60.scope ->Inner blocks do not get access to this

## Block Scope with let statement
  1. A variable with block scope is visible anywhere within the block & not visible outside the block
  1. Inner blocks get access to variables declared in outer blocks
  1. Use let statement to declare variable with block scope
  1. Inner blocks get access to parameters and variables of the blocks that they are defiend within
  1. Basic.60.scope ->Inner blocks do not get access to arguments this
  1. Basic.60.scope ->Inner blocks do not get access to this

```
'use strict';
let fruits = function(){        // Block 1 Start
  let x = "Oranges";
  let y = "Bananas"

  if(true){                     // Block 2 Start.  A variable with function scope is visible anywhere within the function & not visible outside the function
  1. Use var statement to declare variable with function scope
  1. Inner functions get access to parameters and variables of the functions that they are defiend within
  1. Inner functions do not get access to arguments and this
  1. All varaibles declarations with var are hoisted(moved) to the begining of the function

```
'use strict';
var fruits = function(){        // Block 1 Start
  var x = "Oranges";
  var y = "Bananas"

  if(true){                     // Block 2 Start.  Global scope is root of all evil.Any undeclared variable will be have global scope
  1. Use strict mode to force declaration of variables
  1. Add "use strict"; before any other statements.

  ```
  'use strict';
  str = "Bad Variable"; //  will generate ReferenceError: str is not defined
  console.log(str);     //  will never execute
  ```

## Javascript Values are passed or assigned  by value or reference

### numbers, boolean & string values  are assigned by Value
```
var x , y;
x = 5;            // x has a value of 5
y = x;            // y is assigned the value of x. y has a value of 5
console.log (x) ; // prints 5
console.log (y) ; //prints 5

x = x + 1 ;

console.log (x) ; // prints 6
console.log (y) ; //prints 5
```
1. Objects, Arrays and Functions are passed or assigned by Reference

```
var a, b;
a = { name : "Sponge Bob" , age : "100" };
// Value of a is a pointer (reference) to the object in memory which has two properties name and age.
b = a; //Value of b is the pointer (or referene) to the same object in memory;
//a and b point to the same object
console.log (b.name); //will print "Sponge Bob";
b.name = "Patrick Star"
console.log (a.name); //will print "Patrick Star"

```

1. Simple values are passed to functions  by Value
```
var num = 10;
var incremento = function(x){
x = x + 1;
}

//parameter x of incremento will be assigned the value of num when the function is invoked.
incremento(num);
console.log (num); //will print 10;
```

## Closure - Very Cool JavaScript Feature
1. Inner functions have access to outer function's variables and parameters even after the outer function has returned
1. Closures are functions that remember the variables of the outer functions where they were created.

```
let makeFruitify = function(strFruit){
  let fruit = strFruit;
    let fruitfy = function(){
     return fruit;
    }                                  // end of fruitfy
  return fruitfy;
}                                      // end of makeFruitify

let kiwify  = makeFruitify('kiwi');    // kiwify is a closure
                                       // can access var fruit declared in makeFruitify, even after makeFruitify returns.
console.log(typeof (kiwify));          // prints 'function'
console.log (kiwify());                // prints kiwi.

```

# basic.30.objects

## General
1. Objecs are collection of properties
1. A property = a pair of name and value
1. Property name is a string
1. Property value can be boolean, number , string, objects and functions
1. Property values that are functions are called methods

## Creating objects using Object literal notation {}
```
let vehicle   = {};
console.log (typeof(vehicle)); //prints 'object'
```
### Adding properties to an Object
1. Add properties to Object using dot notation and assignment operator
1. To create a property name w/o any values assign undefined to property name (Do not use null)
1. to check if Object has a property use in operator
```
let vehicle   = {};
vehicle.make  = 'Honda';          // Adds a property with name = 'make' and value ='Honda'
vehicle.model = 'Accord';         // Adds a property with name = 'model' and value = 'Accord'
vehicle.year  = undefined;        // Adds a propert with name = 'year' and value = undefined

console.log ('make' in vehicle);  // prints true
console.log ('model' in vehicle); // prints true
console.log ('year' in vehicle);  // prints true even if the value of property is undefined
console.log ('color' in vehicle); // prints false

```

1. You can also Add properties to Object using [] notation and assignment operator
1. The property name have to be enclosed in quotes (or double quotes)

```
let vehicle      = {};
vehicle['make']  = 'Honda';
vehicle['model'] = 'Accord';
vehicle['year']  = undefined;

console.log ('make' in vehicle);  // prints true
console.log ('model' in vehicle); // prints true
console.log ('year' in vehicle);  // prints true
console.log ('color' in vehicle); // prints false
```
1. you can also add properties to an object using notation shown below

```
let vehicle = {
  make  : 'Honda',
  model : 'Accord',
  year  : undefined
};

console.log ('make' in vehicle);  // prints true
console.log ('model' in vehicle); // prints true
console.log ('year' in vehicle);  // prints true
console.log ('color' in vehicle); // prints false
```
### Retriving property values  from an Object
1. Property can be retireved  using . notations or square brackets []

```
let vehicle = {
  make  : 'Honda',
  model : 'Accord',
  year  : undefined
};

console.log (vehicle.make);     // prints 'Honda'
console.log (vehicle['model']); // prints 'Accord'

```
### Updating  property values  from Object
1. Property can be updating  using . notation or square brackets []

```
let vehicle = {
  make  : 'Honda',
  model : 'Accord',
  year  : undefined
};

vehicle.make = "BMW";
vehicle["model"] = "X5";

console.log (vehicle.make);     // prints 'BMW'
console.log (vehicle['model']); // prints 'X5'

```

### Deleting Object properties with a delete operator
```
let vehicle      = {};
vehicle['make']  = 'Honda';
vehicle['model'] = 'Accord';
vehicle['year']  = undefined;

console.log ('make' in vehicle);  // prints true
console.log ('model' in vehicle); // prints true
console.log ('year' in vehicle);  // prints true

delete vehicle.make;
delete vehicle.model;

console.log ('make' in vehicle);  // prints false
console.log ('model' in vehicle); // prints false
console.log ('year' in vehicle);  // prints true

```

###  Objects can have properties that are simple value types (number, string or boolean)
1. vehicle object with make, model and year properties
```
let vehicle   = {};
vehicle.make  = 'Honda';
vehicle.model = 'Accord';
vehicle.year  = 2015;

console.log (vehicle.make)  // prints 'Honda'
console.log (vehicle.model) // prints 'Accord'
console.log (vehicle.year)  // prints 2015
```
### Object Specifiers
1. Objects with simple property values can be passed as arguments to functions
1. This simplifies the declaration and invokation of functions with large number of parameters
1. These objects are called Object Specfiers
```
var printVehicle = function (make, model , color, year, mileage, vinNumber){
  console.log ('make = ' + make);
  console.log ('model = ' + model);
  console.log ('color = ' + color);
  console.log ('year = ' + year);
  console.log ('mileage = ' + mileage);
  console.log ('vinNumber = ' + vinNumber);

}// end of printVehicle

// Invoke printVehicle
printVehicle('Honda','Accord','red','2015','12000','123123213131');
```
```
var betterPrintVehicle = function (spec){
  console.log ('make = '      + spec.make);
  console.log ('model = '     + spec.model);
  console.log ('color = '     + spec.color);
  console.log ('year = '      + spec.year);
  console.log ('mileage = '   + spec.mileage);
  console.log ('vinNumber = ' + spec.vinNumber);

}// end of betterPrintVehicle

let spec       = {};       // Create the Object Specifier
spec.make      = 'Honda';
spec.model     = 'Accord';
spec.color     = 'red';
spec.year      = '2017';
spec.mileage   = '12000';
spec.vinNumber = '1232143253456346';

betterPrintVehicle(spec);  // Invoke betterPrintVehicle
```

### Objects can have properties that are functions.These functions are called methods
```
let vehicle   = {};
vehicle.make  = 'Honda';
vehicle.model = 'Accord';

vehicle.sayHello = function sayHello(){
  console.log ('Hello');
}

console.log(typeof (vehicle.sayHello)) // prints 'function'
vehicle.sayHello();                    // prints 'Hello'
```

### Objects can have properties that are other objects

```
let vehicle   = {};
vehicle.make  = 'Honda';
vehicle.model = 'Accord';

vehicle.driver = {};  // Creates a property with name = 'driver' and value of type object
vehicle.driver.name = 'Sponge Bob';
vehicle.driver.age = 20;

console.log (typeof (vehicle.driver)); // prints 'object'
console.log (vehicle.driver.name);     // prints 'Sponge Bob'
console.log (vehicle.driver.age);      // prints 20
```
## Dictionaries : Collection of Objects
1. A Dictionary is a an Object that has properties whoe's values are also objects
    1. Each property value of the dictionary is an object.
    1. Each property name of the dictionary is a string that uniquely identifies the object
1. Dictionaries are used to store a collecton of related objects
    1. e.g. a collection of all vehicles at a dealership can be stored in a toyotaDealer dictionary
    1. e.g. a collection of all students at Oxford Learning Center in a oxfordSchool dictionary
1. Implementing Dictionaries in JavaScript is hilariously simple
1. Dictionary in JavaScript an Object with a set of name Value pairs where
    1. the property value is an object e.g student = { name = 'ryan' , email =<EMAIL_ADDRESS>, grade = 7 }
    1. the property value is the unique string that identifies student e.g<EMAIL_ADDRESS>1. Steps to create a Dictionary (e.g a dictionary of all students at a school)
    1. Step 0 Find out what makes each student unique and use it as a property name for dictionary object
    1. Step 1 create an empty object to hold the dictioanry e.g. sudentDictionary
    1. Step 2 create a new student object that will be added to the dictionary
    1. Step 3 Add student object created in step 2 to the dicitonary  object using the [] notation
        1. property name = uniquie value of the student object
        1. property value = copy of the student object
    1. Step 4 Repeat Step 2 and 3 for other student objects

```
// Assume there are three students with following properties
// First student  : name = ryan , email =<EMAIL_ADDRESS>, grade = 7
// Second student : name = alex , email =<EMAIL_ADDRESS>, grade = 6
// Third student : name = bella , email =<EMAIL_ADDRESS>, grade = 4
// Also Assume that each student has a unique email

// Create a dictionary of student objects

// step 0 :  find what makes every student unique
// we know that every student has a unique email

//step 1 : Create empty object to hold the dictionary
let studentDictionary = {};

//step 2 : Create a new student object that will be added to the dictionary
let student1    = {};
student1.name   = 'ryan';
student1.email  =<EMAIL_ADDRESS>student1.grade  = 7;

//step 3 : Add student object to the dictionary object using [] notation
// the property name = email of the student
// the property value = the student object
studentDictionary[student1.email] = student1;

//step 3 : Repeat step 2 and 3  for other student objects

// Add student 2 to the dictionary
let student2    = {}
student2.name   = 'alex';
student2.email  =<EMAIL_ADDRESS>student2.grade  = 6;

studentDictionary[student2.email] = student2;

// Add student 3 to the dictionary
let student3    = {}
student3.name   = 'bella';
student3.email  =<EMAIL_ADDRESS>student3.grade  = 4;

studentDictionary[student3.email] = student3;

console.log(studentDictionary);

// find student ryan in student dictionary
// to find ryan in the dictioanry we need to know ryan's email as this makes him unique
let student =<EMAIL_ADDRESS>console.log (student.grade);  // prints 7
console.log (student.name) ; // prints 'ryan'

// delete student ryan from  student dictionary
delete<EMAIL_ADDRESS>;
let ryan =<EMAIL_ADDRESS>console.log (typeof(ryan)); // prints undefinedd

```

## Factories : Making  objects with function factories
1. All properties of an object are visible.This implies these can be read and updated by anybody
1. Some applications require private variables and private methods.
1. The best way to create objects with private variables and functions is to use a function factory.
1. A factory is a function that returns an object that hides its  private variables
1. A factory function does the following
    1. Step 1 : Create a new  empty object
    1. Step 2 : Defines private variables and methods. These are vars with function scope, hence are accessible only inside the function
    1. Step 3 : Adds methods to the object.These methods will remember vars define in step 2 even after factory function returns (closure)
    1. Step 4 : Returns the object defined in step 1

### Create a factory function for vehicle objects
```
let vehicleFactory = function(spec){

  // Step 1 : Create new Object
  let vehicle   = {};

  // Step 2a : Declare and initialize private variables

  let make  = '';
  let model = '';

  // Step 2b : Declare private functions

  let getMake = function getMake(){
    return make;
  }// end of getMake

  let setMake = function setMake(strMake){
    if (typeof (strMake) !== 'string'){
      throw 'strMake is not of type string';
    }
    make = strMake;
  }// end of setMake

  let getModel = function getModel(){
    return model;
  }// end of getModel

  let setModel = function setModel(strModel){
    if (typeof (strModel) !== 'string'){
      throw 'strModel is not of type string';
    }
    model = strModel;
  }// end of setModel

  // Step 3 : Add public methods to the object

  vehicle.getMake  = getMake;
  vehicle.setMake  = setMake;
  vehicle.getModel = getModel;
  vehicle.setModel = setModel;

  // Step 4 : return the object
  return vehicle;

}
```
### Use vehicle facrory to create Objects
1. Create an objects with Factory function
```
let dadCar = vehicleFactory();   // create dad's Car object using factory function

console.log (dadCar.make)        // prints undefined make is a private variable
console.log (dadCar.model)       // prints undefined model is a private variable

dadCar.setMake('BMW');           // set make for dadCar
dadCar.setModel('X5');           // set model for dadCar
console.log (dadCar.getMake());  // prints  'BMW'
console.log (dadCar.getModel()); // prints  'X5'

```
```
let ryanCar = vehicleFactory();   // create ryan's Car object using factory function
ryanCar.setMake('Ford');          // set make for ryanCar
ryanCar.setModel('F150');         // set model for ryanCar
console.log (ryanCar.getMake());  // prints  'Ford'
console.log (ryanCar.getModel()); // prints  'F150'

```
## Modules
1. Modules can be used to keep a Factory Functions in a separate file
1. This improves code quality and readability
1. [Nodejs Modules](https://nodejs.org/api/modules.html#modules_modules)

### Creating a Module using module.exports
1. To create a module e.g. for fruitsFactory function that generates a fruits objects
     1. Create a file ./lib/fruitsFactory.js. This file will be the module
     1. Create the function factory e.g. let fruitsFactory = function fruitsFactory(){};
     1. At the end of the file export the factory using  module.exports = fruitsFactory;
     1. Variables declared in the module are private as nodejs will wrap the module in a function
          1. in the example below fruitsFactory will be private

```
// File ./lib/fruitsFactory.js
'use strict';
let fruitsFactory = function fruitsFactory(){

  let fruitBasket  = {};                      // Step 1

  let fruits = [];                            // Step 2
  let addFruit = function addFruit(strFruit){
     fruits.push(strFruit);
  };
  let removeFruit = function removeFruit(){
    let fruit = fruits.pop();
    return fruit;
  };
  let getCount = function getCount(){
    return fruits.length;
  }

  fruitBasket.addFruit    = addFruit;        // Step 3
  fruitBasket.removeFruit = removeFruit;
  fruitBasket.getCount    = getCount;

  return fruitBasket;                         // Step 4

};                                            // end of fruitsFactory

module.exports = fruitsFactory;               // export the fruitsFactory function
```
### Using a module with require statement
1. To use a module from a different file e.g. ./test.js
     1. Import the function factory  using require statement
     1. Require statements are hoisted to the top of the file
     1. All require statements should be declared at the top of the file
```
// File ./test.js
let fruitsFactory = require ('./lib/fruitsFactory');
console.log (typeof (fruitsFactory));                // prints 'function'
let fruits = fruitsFactory();
console.log (typeof (fruits));                       // prints 'object'
console.log (fruits.getCount());                     // prints 0
fruits.addFruit("kiwi");
console.log (fruits.getCount());                     // prints 1
```

repository: vishalz/hello-js

repo_name: vishalz/hello-js


text:
Solana DNS

A simple DNS server using the high-performance Solana blockchain to store signed records.

(Implemented in JavaScript and Solana BPF Rust, w/ an optional REST API + Web UI)

a.k.a "who-dat over very-fast-brick-string"

Why Solana? |
How does DNS work normally? |
Quickstart |
Documentation |
Manual Setup |
Architecture |
Configuration |
Usage

(Based on code from hbouvier/dns and solana-labs/example-messagefeed, but not affiliated with either project officially)

WARNING: this project is not actually implemented yet! Follow the TODOs for progress and check back soon for runnable code!

## Why Solana?

- [Provable history by design.](https://medium.com/solana-labs/proof-of-history-a-clock-for-blockchain-cf47a61a9274)
  Records are cryptographically provable to have existed at a given time.

- [Inherently immutable.](https://solana-labs.github.io/book/#what-is-a-solana-cluster)
  Past history can never be modified, whether by accident or maliciously.

- [Inherently distributed and fault-tolerant.](https://solana-labs.github.io/book/validator-proposal.html)
  A globally-distributed network of nodes serve as validators, data replicas, and leaders in the event of a fail-over.

- [Inherently authenticatable.](https://github.com/solana-labs/example-messagefeed#new-user-sign-up)
  All records are signed with your wallet private key, and can be verified against your public key.
  Remember though, for true authentication *signing alone is meaningless unless your public keys are provably linked to your identity* (e.g. via public PGP signed message, Keybase.io, etc).
  Solana is not an identity provider, but Solana can link accounts to other identity providers like [Google Auth](https://github.com/solana-labs/example-messagefeed#new-user-sign-up).

- [It's fast as hell.](https://solana.com/solana-milestone-a-multinode-testnet/)
  The network leader can theoretically handle **710,000 TPS**, and this library additionally caches records locally up to the signed TTL.
  Solana [ain't your average blockchain](https://medium.com/solana-labs/proof-of-history-explained-by-a-water-clock-e682183417b8), it pulls all this off with **[no sharding or validation delays](https://solana.com/no-sharding-podcast-episode-2-how-does-solana-work/)**.
  See the [Solana Architecture](#Solana-Architecture) section for more info.

 - [DNS on the Blockchain makes sense.](https://diode.io/distributed-infrastructure/Why-DNS-on-Blockchain-is-the-next-step-after-DNS-over-HTTPS-19231/)
   Given all the properties above, having DNS as the authenticated source-of-truth for DNS is not a bad idea (whether to augment DNSSEC or replace it entirely).
   Caching layers that improve backwards-compatibility and speed can always be built on top, but everything gets easier when the underlying store is fast, immutable, globally-consistent, and authenticated.

 This project is still in idea-phase, so read these as goals, not guarantees!**

---

### How does DNS work normally?

(click sections to expand)

This is a simplified example of a standard DNS setup process (without Solana DNS or DNSSEC):

1. You register a domain `example.com` on the Namecheap Registrar

2. You set your authoritative nameservers in the NameCheap control panel to `ns1.digitalocean.com`

3. NameCheap pushes the change to the [root dns servers](https://www.iana.org/domains/root/servers) for your TLD,
in this case the root servers for `.com` (this is handled outside of the DNS system,
usually using a protocol called the [Extensible Provisioning Protocol (EPP)](http://www.ietf.org/iesg/implementation/report-rfc4930-4934.txt))

4. The root DNS servers update their NS records to point to your new authoritative name server `ns1.digitalocean.com`

5. In your DigitalOcean account you configure the domain's DNS and set the `example.com` `A` record to `<IP_ADDRESS>`

Then a user comes along and makes a DNS request for your domain `example.com` using their configured DNS upstream server `<IP_ADDRESS>`:

1. User's device sends a DNS query to `<IP_ADDRESS>:53/udp` asking for the `example.com` `A` record (in plain text, unencrypted)

2. Assuming `<IP_ADDRESS>` doesn't have the record cached, it asks the root domain servers "what nameserver can I use to look up this record?"

3. The `.com` root domain server responds with `ns1.digitalocean.com`

4. `<IP_ADDRESS>` then sends a query to `ns1.digitalocean.com` asking for the `example.com` `A` record

5. `ns1.digitalocean.com` responds with `<IP_ADDRESS>` to `<IP_ADDRESS>`

6. `<IP_ADDRESS>` caches this record and passes along the response back to the user

7. The user receives back an unencrypted, unsigned, plaintext response containing `<IP_ADDRESS>`,
stating that `<IP_ADDRESS>` was the server that answered the request

Unfortunately this system has a number of major security flaws! Can you spot some of them?

- there are many layers of *implicit trust* with no authentication or verification mechanism. You have to trust that
  + `ns1.digitalocean.com`,
  + `<IP_ADDRESS>`,
  + the `.com` root servers,
  + and every middle-box between you and them
  are **all** non-malicious, free of bugs, and are otherwise functioning perfectly.

- the requests and responses are entirely in plaintext, making it trivial for middle-boxes to intercept, record, and modify query content
- the responses are unsigned and unauthenticated, meaning the user has no idea if the you were the one who created
  that DNS record, or if a malicious/buggy/hacked middle-box just decided to return a different value randomly.
  With no signature or public key to verify against, there's no way to know whether the response value has been tampered with.

Enter DNSSEC & DNS-over-HTTPS... two separate technologies aiming to solve two of the biggest issues.

- DNSSEC partially fixes the authentication issue by allowing people to pin a public key along with their authoritative
name servers at the registrar level (NameCheap) / root DNS level (`.com` root servers). The user can then use the corresponding
private key (that only they have access to), to sign all records added to their nameserver (`ns1.digitalocean.com`).
DNSSEC-compatible clients can then receive signed DNS query responses, and can verify the signatures are valid against the public
key published at the root level.

- DNS-over-HTTPS (DOH) doesn't add any kind of authentication to the individual records, but it does allow users to form a direct,
encrypted connection to their upstream DNS servers, and authenticate the server's identity using their public SSL certificate.
This makes one link in the chain trusted, but it does nothing for the links upstream from the user's DNS server unless they're also using DNS over HTTPS
or an equivalent encrypted transit method (which luckily many major providers do use).

So what does Solana add to the equation?

It removes the root DNS servers from the trust equation (e.g. the `.com` TLD servers).  Remember that they have ultimate control over all record authentication because
they could choose to ignore or maliciously change the DNSSEC public key that you published via the registrar.  This implicit trust can be removed
in Solana DNS because the public key is the user's wallet public key, which is intrinsically tied to their identity on the platform.
Solana has no power to change the public key because the chain forms an immutable record, and only later statements signed with a revocation key
are recognized by clients as authorized to change the public key in control of a given domain.

This isn't just a case of "slap a blockchain on it and hope it gets better", this is a true novel distributed database-style
solution that hasn't been feasible with traditional blockchains. Running usable DNS on blockchains is now feasible with the advent of
fast proof-of-history chains, because it enables updates to happen within DNS TTL windows like 30sec, which are well below
the 10min verification time that a chain like Bitcoin would require. Because changes can also be synchronously applied
to appear to everyone across the world at the same time, we can also lose the "eventual consistency"
and propagation delay issues that plagued standard DNS systems in the past.

Solana DNS can also retain the nice distributed properties of past DNS systems.
Because all records are signed all the way up to the root using the domain owner's public key, any node
can serve up records without users having to implicitly trust them.  The query results
will always arrive signed with a key that can be verified to ensure malicous middle-boxes cant get away with modifying records.

Potential problems?

- Solana may be fast, but the RPC communication with the Solana chain may be significantly slower than DNS over UDP
- If RPC communication becomes the bottleneck, we end up having to implement time-synchronized caching servers with fairly
complex validation/staking mechanics to penalize clock drift and inadherence to signed record TTL expiry times.  This problem becomes slightly simpler
if we only allow caching on localhost, with no middleboxes between the local Solana DNS server and the Solana chain API.
- It may not be necessary to replace DNSSEC entirely, it's possible to just sign the same root public key used on the TLD
in Solana, and use DNSSEC from there on down the chain (checking against the Solana root key instead of the implicitly trusted root-server-published key)
- The mechanics around domain ownership verification need to be figured out (or whether it's even necessary with Solana DNS)
- The mechanics of pinning identities to keys needs to be figured out (whether via staking, 3rd party identity providers, or something else)
- The mechanics of key issuing, rotating, and revocation need to be figured out (proper revocation is haaard, we dont want domains being lost forever to the ether because someone lost a private key)

Given the power of an immutable, globally sychronized database, with key-based identity baked in,
many of the distributed-systems and authentication problems that have plagued DNS in the past become drastically easier to solve.
Unfortunately, designing DNS system to seamlessly augment or entirely replace existing DNS authentication mechanisms is incredibly complex.
Though our ambitions are big, this project will likely have to make some decisions early on to narrow the scope and pick a few core features to focus on as a proof-of-concept.

---

## Quickstart

This installs all the dependencies, creates a free Solana account on the beta testnet, uploads the on-chain code, and runs a local dns server on `<IP_ADDRESS>:5300` using Solana as the backing datastore.
```bash
git clone https://github.com/pirate/solana-dns
cd solana-dns

./bin/setup
./bin/server --bind-dns=<IP_ADDRESS>:5300 --bind-http=<IP_ADDRESS>:5380

dig @<IP_ADDRESS> -p 5300 google.com
```
If you don't like helper scripts installing packages and want to understand/fine-tune the setup, or if you encounter any issues, follow the [Manual Setup](#Manual-Setup) steps below.

---

# Documentation

Manual Setup |
Architecture |
Configuration |
Usage

---

## Manual Setup

(click sections to expand)

1. Install the language dependencies...

 - Rust https://www.rust-lang.org/tools/install
   `curl https://sh.rustup.rs -sSf | sh` / `apt install rustup; rustup-init` / `brew install rustup; rustup-init`

 - JavasScript https://nodejs.org/en/download/package-manager/
    `apt install node; npm -g i npm` / `brew install node; npm -g i npm`

 - Docker https://docs.docker.com/install/
    Required because the Solana Rust BPF builder runs in Docker for better repeatability.

2. Clone the repo & install the project dependencies...

```bash
git clone https://github.com/pirate/solana-dns
cd solana-dns

npm install
```

3. Create an account on your desired Solana network...

Running code on Solana requires an "account"/wallet with tokens that will be used to run the on-chain part of the DNS server.
(Similar to how running Ethereum DAPPs on-chain requires spending some tokens in exchange for CPU time)
Choose which Solana network you want to store your records in:

- **Using the public beta testnet** (easiest, all records publicly accessible, **free**):
    You automatically get free air-dropped tokens to run code on the beta net.
    ```bash
    ./bin/signup --net=beta --save-config=./secrets.env  # or use --net=edge
    ```

- **Using a local testnet** (harder, no data accessible off your local machine, **free**):
   You get infinite free tokens on your local test net because you own it!
   ```bash
   ./bin/localnet > localnet.log &
   ./bin/signup --net=localnet --save-config=./secrets.env
   ```

- **Using the public mainnet** (hardest, all records publicly accessible, **real $ needed**):
   You have to purchase SOL tokens via an exchange to run code on the main net.
   ```bash
   # Not available yet, check https://solana.com/tds/ for updates
   ```

4. Upload the on-chain side of the program using your account...

Build and upload the Rust BPF program that runs on the Solana net to handle requests from your local `solana-dns` server.
```
./bin/build
./bin/upload --config=./secrets.env
```

5. Run the solana-dns server on localhost...

```bash
./bin/server --bind-dns=<IP_ADDRESS>:5300 --bind-http=<IP_ADDRESS>:5380 --upstream=<IP_ADDRESS>,<IP_ADDRESS>
```

6. You're done! Your `solana-dns` server should be accessible via the bound ports... ✅

 - **To query it via DNS:**
    ```bash
    dig @<IP_ADDRESS> -p 5300 google.com
    ```

 - **To query it via the REST API:**
    ```bash
    curl http://<IP_ADDRESS>:5380/dns/api/v1/name/google.com
    ```

 - **To view the Web UI:**
    Open http://<IP_ADDRESS>:5380

---

## Architecture

Data Flow |
Execution Flow |
Solana Architecture

### Data flow

The data flows through the stack like this: (click to expand)

- ⬇👩💻📃 **User**
    *Makes requests via DNS or HTTP.*
    `./ui/index.js` (runs in-browser) / direct request via DNS or REST API

- ⬇🖥⬆ **Local Node Server**
    *Main JavaScript logic handles CLI commands, DNS queries, and HTTP requests.*
    `./server/server.js` (runs locally)  / `./server/dns-client.js` (runs locally, resolves any records not found in Solana)

- ⬇🌐⬆ **Solana Network API**
    *Calls out via Solana w3 JSON RPC API to the Solana network.*
    `./network/api.js` (runs locally, calls configured Solana Network's endpoint, e.g. `https://beta.testnet.solana.com:8443`)

- ⬇⛓⬆ **Solana BPF Rust Program On-Chain**
    *The uploaded BPF Rust program spends your account tokens to run on the Solana network and perform reads/writes of stored data.*
    `./network/kvstore.rs` (gets uploaded and runs on-chain)

- ⬇➡⬆ **Solana Blockchain**
    *Solana provides the data storage layer to hold the records.*
    `<Solana internals>` (stored as text blobs on-chain)

### Execution Flow

The code execution flow looks like this: (click to expand)

1. New Solana account gets created with some free air-dropped tokens (needed to run code on-chain)
   `./bin/signup` -> `./network/signup.js`
   (only works on testnet/localnet, you're not getting free tokens on mainnet that easy 😉)

2. BPF Rust program gets uploaded to the Solana chain under new account
   `./bin/upload` -> `./bin/build ./network/kvstore.rs` -> `./network/upload.js ./network/kvstore.rs`
   BPF Loader runs to push program to chain via configured Solana network's endpoint, e.g. `https://beta.testnet.solana.com:8443`

3. REST API / DNS queries get handled by local node server
   `./bin/server` -> `./server/server.js` -> `./server/http-server.js`,`./server/dns-server.js`

4. Local node server calls out to Solana network via Solana Web3 JSON RPC API
   `./network/api.js` -> `https://beta.testnet.solana.com:8443`

5. BPF Rust program runs on Solana network to handle record read/write requests
   `./network/kvstore.rs` -> `<solana internal API>`
   (Spends account tokens in exchange for the CPU time)

6. Solana blockchain handles storage requests
   `<solana internal API>` -> `<solana blob storage>`

7. If record is found, results are returned back up the stack, if not, they're resolved via the upstream DNS servers
   `./server/dns-client.js` -> `<upstream DNS servers>`

### Solana Architecture

More info on Solana's novel proof-of-history design, architecture, and available APIs can be found here:

#### Intro
- https://solana.com
- https://solana.com/developers/
- https://solana-labs.github.io/book/
- https://github.com/solana-labs/whitepaper/blob/master/solana-whitepaper-en.pdf
- https://medium.com/solana-labs/proof-of-history-explained-by-a-water-clock-e682183417b8
- https://explorer.solana.com/
- https://www.reddit.com/r/solana/

#### Example Code
- https://github.com/solana-labs/example-webwallet
- https://github.com/solana-labs/example-messagefeed
- https://github.com/solana-labs/example-tictactoe

#### Source Code & API Reference
- https://solana-labs.github.io/solana-web3.js/
- https://solana-labs.github.io/solana-web3.js/class/src/bpf-loader.js~BpfLoader.html
- https://github.com/solana-labs/rust-bpf-builder
- https://github.com/solana-labs/solana
- https://github.com/solana-labs/blockexplorer
- https://github.com/solana-labs/solminer
- https://crates.io/users/solana-grimes
- https://github.com/solana-labs/solana/tree/master/client/src
- https://github.com/solana-labs/solana/tree/master/programs
- https://docs.rs/solana-wallet/0.17.2/solana_wallet/wallet/enum.WalletCommand.html
- https://docs.rs/solana-kvstore/0.17.2/solana_kvstore/struct.KvStore.html

---

## Configuration

Config options can be passed to Solana DNS commands (e.g. `./bin/server`) in a few different ways:

1. [Configuration File](#Configuration-File) passed via `--config=path/to/file.env`
2. [Environment Variables](#Environment-Variables) (which override any existing options in the config file)
3. [CLI Parameters](#CLI-Parameters) (which override both env variables and config file params)

### CLI Parameters

Click to expand CLI parameter docs

#### `--config=path/to/file.conf`

**Default:** `--config=./secrets.env`
**Example:** `--config=/etc/solana/credentials.conf`

Specify the path to the file containing your network config and account credentials used to connect to a Solana network.

For more info on the config file and options available within, see the [Configuration File](#Configuration-File) section.

#### `--bind-dns=[host]:[port]`

**Default:** `--bind-dns=<IP_ADDRESS>:5300`
**Example:** `--bind-dns=<IP_ADDRESS>:53`

Specify the local [ip]:[port] to bind the DNS server to. It must be `<IP_ADDRESS>:53` to act
as a standard public DNS server that can accept requests from any client (instead of just localhost).

See the [instructions below](#start-the-server-on-port-53) if you want to bind to port `53` instead.

#### `--bind-http=[host]:[port]`

**Default:** `--bind-http=off`
**Example:** `--bind-http=<IP_ADDRESS>:5380`

Specify the local [ip]:[port] to bind the web UI server to. It must be `<IP_ADDRESS>:[port]` in
order to accept HTTP requests from any client (instead of just localhost).

#### `--upstream=[host]:[port],[host2]:[port2],...`

**Default:** `--upstream=off`
**Example:** `--upstream=<IP_ADDRESS>,<IP_ADDRESS>,<IP_ADDRESS>,dns.example.com:5353`

Specify which upstream DNS servers to send requests to when the query cannot be resolved via Solana DNS.
The default is `off`, meaning it will return "no result found" if the record is not in the Solana store.

To make it a usable DNS server for all queries, and not just records stored in Solana, it's recommended
to run with a few upstream servers capable of resolving normal internet-level DNS records.

### Configuration File

Click to expand configuration file docs

When running the server, the path to the config file should be specified via the `--config=path/to/file.env` CLI param.

The config file is initially generated during setup when running:
```bash
./bin/signup --net=beta --save-config=./secrets.env
```
It can also be modified after the initial signup to change the credentials or include some additional options.

The config file must be in Docker/Bash compatible [`.env` format](https://docs.docker.com/compose/env-file/#syntax-rules), and can contain the following parameters:
```bash
SOLANA_NETWORK_NAME=beta
SOLANA_NETWORL_ENDPOINT=https://beta.testnet.solana.com:8443

SOLANA_USER_ID=[unique user id here]
SOLANA_USER_PUBLIC_KEY=[public key here]
SOLANA_USER_PRIVATE_KEY=[private key here]
SOLANA_USER_AUTH_GOOGLE=[optional Google email address here]

# Optionally specify additional DNS server config here
# these options are equivalent to ther respective CLI params
SOLANA_DNS_BIND_DNS=<IP_ADDRESS>:5300
SOLANA_DNS_BIND_HTTP=<IP_ADDRESS>:5380
SOLANA_DNS_UPSTREAM=<IP_ADDRESS>,<IP_ADDRESS>,<IP_ADDRESS>
```

### Environment Variables

Click to expand environment variable docs

The options in the config file can also be passed as environment varaibles using the same format. e.g.:
```bash
env SOLANA_DNS_BIND_DNS=<IP_ADDRESS>:5300 ./bin/server ...
```

(This works well to pass config when running inside a Docker container)

---

## Usage

CLI |
REST API |
DNS over HTTPS API |
JSON API |
Web UI

---

### CLI

Click to expand CLI usage docs

#### Start the server

See the [Configuration](#Configuration) section for a list of the options available.
```bash
./bin/server [options]
```

To bind to any ports below 1000, most systems require running the program as root.
```bash
sudo ./bin/server [options]
```

#### Start the server on port 53

By default the DNS server listens on a custom UDP port `5300` in order to avoid requiring `sudo` or conflicting
with any existing local DNS server. To bind to the the standard DNS port (UDP `53`) instead, follow the steps below.

1. Check to see if a DNS server is already running on `<IP_ADDRESS>:53`
    ```bash
    sudo nc -ulp 53 || echo "port already in use"
    ```
2. On Ubuntu: you may have to stop `systemd-resolvd` (the system DNS resolver that binds to `:53` by default)
    ```bash
    # to stop it immediately, run:
    systemctl stop systemd-resolvd

    # then, if you want to prevent it from starting the next time you reboot, run:
    systemctl disable systemd-resolvd

    # make sure /ets/resolv.conf exists and has at least one non-local upstream DNS server
    echo "nameserver <IP_ADDRESS>" >> /etc/resolv.conf
    ```
2. Once the port is confirmed open, you can bind Solana-DNS to `:53`
    ```bash
    # listening on ports below 1000 requires sudo on most systems

    # to run a server that responds to DNS queries from localhost only, run:
    sudo ./bin/server --bind-dns=<IP_ADDRESS>:53

    # to run a server that responds to DNS queries from your local network only, run:
    sudo ./bin/server --bind-dns=x.x.x.x:53  # replace x.x.x.x with your LAN IP

    # to run a public server that responds to DNS queries from any location, run:
    sudo ./bin/server --bind-dns=<IP_ADDRESS>:53
    ```
3. Optional: tell your system to use the local DNS server for all queries:

    ```bash
    # edit /etc/resolv.conf and put this line *above* any other "nameserver x.x.x.x" lines
    nameserver <IP_ADDRESS>
    ```
    On macOS you can set this under:
    ```
    System Preferences > Network > Advanced > DNS > [+]
    <IP_ADDRESS>
    (drag it to the top of the list if there are other entries)
    ```

#### Add/Modify/Delete Records

TODO

---

### Rest API

Click to expand Rest API docs

#### GET `/api/dns/A/{domain}`

Return the IP address for the given given domain.

#### PUT `/api/dns/A/{domain}`

Create or Modify the IP address for the given domain.

#### DELETE `/api/dns/A/{domain}`

Forget the IP address record for the given domain.

#### GET `/api/dns/A/.`

List all host to IP address mappings that the local server knows about.

#### DELETE `/api/dns/A/?force=true`

Forget all records.

#### GET `/api/dns/zone`

Return the DNS ZONE.

#### GET `/api/dns/status`

Return the DNS server status.

---

### DNS over HTTPS API

TODO: implement a Google/Cloudflare-compatible DNS over HTTPS API

- https://developers.google.com/speed/public-dns/docs/doh/
- https://developers.cloudflare.com/<IP_ADDRESS>/dns-over-https/request-structure/

---

### JSON API

TODO: implement a Google/Cloudflare-compatible DNS over HTTPS JSON API

- https://developers.google.com/speed/public-dns/docs/doh/json
- https://developers.cloudflare.com/<IP_ADDRESS>/dns-over-https/json-format/

### Web UI

TODO: document Web UI features.

---

## TODO

#### Core Implementation

- [ ] Pull in config loading and CLI env setup boilerplate from https://github.com/pirate/bash-utils
- [ ] Implement `./bin/signup` (based on https://github.com/solana-labs/example-messagefeed/blob/master/src/util/new-system-account-with-airdrop.js)
- [ ] Implement `./bin/upload` to upload the compiled Rust BPF program on-chain (based on https://github.com/solana-labs/example-messagefeed/blob/master/src/server/message-feed.js#L85)
- [ ] Implement `./bin/build` to compile the Rust BPF program (based on https://github.com/solana-labs/example-messagefeed/blob/master/bpf-rust-programs/messagefeed/do.sh)
- [ ] Implement `./network/kvstore.rs` the Rust BPF kvstore + re-usable for other projects (based on https://github.com/solana-labs/example-messagefeed/blob/master/bpf-rust-programs/messagefeed/src/lib.rs)
- [ ] Implement `./network/api.js` to talk to the Rust BPF program running on the Solana network (based on https://github.com/solana-labs/example-messagefeed/blob/master/src/programs/message-feed.js)
- [ ] Implement `./bin/server` -> `./server/server.js` Solana DNS server to call out to API and get/set DNS key:value records (based on https://github.com/hbouvier/dns/blob/master/lib/dns.js)
- [ ] Implement `./server/dns-server.js` to bind to a UDP port and serve DNS queries

#### Lower Priority

- [ ] Add support for more DNS record types besides `A` records (e.g. `CNAME`, `TXT`, etc.)
- [ ] Implement `./server/http-server.js` to bind to a TCP port and serve HTTP Web UI and REST API
- [ ] Implement `./server/dns-client.js` to fetch records from upstream servers when not found on Solana
- [ ] Add support for adding/removing/modifying DNS records via CLI
- [ ] Add config file / environment variable support for hardcoded DNS records
- [ ] Add support for DNS-over-HTTPS API & JSON API
- [ ] Finish documentation for the Web UI and REST, DNS-over-HTTP, and JSON APIs

license: MIT

branch_name: refs/heads/master

extension: md

license_type: permissive


text:
---
layout: default
---

# 1997-10-09 - Re: access to storage keys, NOT comms keys!

## Header Data

From: Anonymous<EMAIL_ADDRESS>To<EMAIL_ADDRESS>Message Hash: 867278dd1dc4f470c74db0fff5328ed7a7a3d7d54f2525f95a2e486412d513dc

Message ID<EMAIL_ADDRESS>Reply To: _N/A_

UTC Datetime: 1997-10-09 02:27:28 UTC

Raw Date: Thu, 9 Oct 1997 10:27:28 +0800

## Raw message

```
{% raw  %}From: Anonymous<EMAIL_ADDRESS>Date: Thu, 9 Oct 1997 10:27:28 +0800
To<EMAIL_ADDRESS>Subject: Re: access to storage keys, NOT comms keys!
Message-ID<EMAIL_ADDRESS>MIME-Version: 1.0
Content-Type: text/plain

Here is what leading cryptographers say about email key recovery, from
http://www.crypto.com/key_study/report.shtml.  This includes respected
figures like Bruce Schneier, Matt Blaze, Ron Rivest, Ross Anderson,
Whit Diffie, and more.

   2.1 Communication Traffic vs. Stored Data

   While key ``recoverability'' is a potentially important added-value
   feature in certain stored data systems, in other applications of
   cryptography there is little or no user demand for this feature. In
   particular, there is hardly ever a reason for an encryption user to want
   to recover the key used to protect a communication session such as a
   telephone call, FAX transmission, or Internet link. If such a key is lost,
   corrupted, or otherwise becomes unavailable, the problem can be detected
   immediately and a new key negotiated. There is also no reason to trust
   another party with such a key. Key recoverability, to the extent it has
   a private-sector application at all, is useful only for the keys used
   to protect irreproducible stored data. There is basically no business
   model for other uses, as discussed below.

   In stored data applications, key recovery is only one of a number of
   options for assuring the continued availability of business-critical
   information. These options include sharing the knowledge of keys
   among several individuals (possibly using secret-sharing techniques),
   obtaining keys from a local key registry that maintains backup copies,
   careful backup management of the plaintext of stored encrypted data, or,
   of course, some kind of key recovery mechanism. The best option among
   these choices depends on the particular application and user.

   Encrypted electronic mail is an interesting special case, in that it
   has the characteristics of both communication and storage. Whether key
   recovery is useful to the user of a secure E-mail system depends on
   design of the particular system.

   The government, on the other hand, proposes a key recovery infrastructure
   that applies to virtually all cryptographic keys, including (especially)
   those used to protect communications sessions.

They say that key recovery is not appropriate for transient keys used
during a communication session.  However, email is a special case, having
characteristics of both communication and storage.  In some systems,
email may be archived for long periods of time in the same format that
it was received.  For such systems there is a business case for key
recovery in email.

{% endraw %}
```

## Thread

+ Return to [October 1997](/archive/1997/10)

+ Return to "[Adam Back <aba@dcs.ex.ac.uk>](/authors/adam_back_aba_at_dcs_ex_ac_uk_)"
+ Return to "[Anonymous <nobody@REPLAY.COM>](/authors/anonymous_nobody_at_replay_com_)"

+ 1997-10-09 (Thu, 9 Oct 1997 10:27:28 +0800) - Re: access to storage keys, NOT comms keys! - _Anonymous<EMAIL_ADDRESS>  + 1997-10-09 (Thu, 9 Oct 1997 17:08:48 +0800) - [Re: access to storage keys, NOT comms keys!](/archive/1997/10/3afec1bdd6f7d365970bfdff11f5fd004b3e21c74e9a2da6008bfeaa76033f4b) - _Adam Back<EMAIL_ADDRESS>

gha_license_id: MIT


text:
# [agar-mini-map](https://github.com/dimotsai/agar-mini-map)
A mini map which is able to show your location on http://agar.io/

## Installation

### Install for user script managers

The user script managers will automatically load agar-mini-map for you.

1. Install the user script manager
    * Chrome, Chromium: [Tampermonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo)
    * Firefox: [greasemonkey](https://addons.mozilla.org/zh-TW/firefox/addon/greasemonkey/)
    * Opera: [Tampermonkey](https://addons.opera.com/zh-tw/extensions/details/tampermonkey-beta/?display=en)
    * Safari: [Tampermonkey](https://tampermonkey.net)
2. Install agar-mini-map
    1. Go to https://greasyfork.org/en/scripts/10286-agar-mini-map
    2. Click `Install this script`

### Manually install for other browsers

1. Simply open up JavaScript Console
2. Enter the code in [agar-mini-map.js](https://raw.githubusercontent.com/dimotsai/agar-mini-map/master/agar-mini-map.js) into console

Note: If you are taking this approach, you might have to re-select server to make it work.

## Screenshots

### Latest
![screenshot_2](http://i.imgur.com/35d7m5y.png)
![screenshot_3](http://i.imgur.com/xUz7xx0.png)

### Old Versions
(<= v0.24)![screenshot_1](http://i.imgur.com/FgujOgA.png)

## Issues

* https://github.com/dimotsai/agar-mini-map/issues

## Related projects

* [iamgyz/Agar-server-selection](https://github.com/iamgyz/Agar-server-selection)


text:
# Exoop

Portable for your scoop apps.

## Installation

```powershell
git clone https://github.com/AnyThund/exoop.git
cd exoop
python setup.py install
```

## Usage

```shell
$ exoop
```

This command will export installed apps default on your Desktop, named apps.txt. The same function as `scoop export > apps.txt`.

```shell
$ exoop -h
```

Show help.

```shell
$ exoop -z
```

Export all installed apps' installation packages into 'apps.zip' default on your Desktop.

```shell
$ exoop -n name
```

Rename output file name to `name.txt`.

```shell
$ exoop -d path
```

Choose another path your file export to.

repository: AnyThund/exoop

repo_name: AnyThund/exoop


text:
## Document on HCI final project

### Introduction

Space War is a 3D web game using React.js as the front end frame and Three.js as the 3D frame. In this game, you can use keyboard to manipulate the spaceship to do many different  motions like accelerating and rolling. When the enemy appears in your sight randomly, you can aim at it and click the mouse in order to shoot at it. The system presents you with more game feeling by hud and vivid explosion effect both during your or your enemies' death.On the up-right corner there is a panal for you to adjust the battlefield environment in real time.

**Overview：**

![](.\img\overview.png)

**Demo**:<https://greilfang.github.io/Air-War/begin.html>

### Basic Opeartion

```latex
[W] : accelerate

[S] : moderate

[A] : turn left

[D] ：turn right

[R] : directly go up

[F] : directly go down

[MOUSE MOVING UP] : fly upward

[MOUSE MOVING DOWN] : fly downward

[MOUSE CLICKING LEFT] : shoot with bulleCt

[MOUSE CLICKING RIGHT] : shoot with missile
```

### Component Structure

The files(important) in the project are as follow：

**config：**

| name  | description                                       |
| ----- | ------------------------------------------------- |
| env   | some basic setting and get the client environment |
| paths | record and confirm the entrance of the project    |

**node module：**

The imported external modules.

**public:**

| name       | description                                                  |
| ---------- | ------------------------------------------------------------ |
| assets     | some figures like the parameters of enemies                  |
| css        | the style of the page                                        |
| begin.html | the begin page                                               |
| index.html | the main scene of the game using React,all the elements are imported as components |

**scripts:**

| name     | description                                       |
| -------- | ------------------------------------------------- |
| build.js | give out the compile message during webpack build |
| start.js | settings to run the web server                    |
| test.js  | unit tests to check the configuration and data    |

**src:**

| name           | description                                                  |
| -------------- | ------------------------------------------------------------ |
| controls       | all the controls in the game,about mouse and keyboard        |
| drones         | the initialization of enemies, upload bar an so on           |
| events         | just import 'PubSub'                                         |
| hud            | the hud                                                      |
| modules        | present the parameters in 'controls',also the  parameters of sky effect. |
| ocean          | the ocean                                                    |
| particles      | the particle effect from SPE package                         |
| postprocessing | all the beautiful rendering effect(imported from external).  |
| sky            | the sky                                                      |
| sound          | the sound resources                                          |
| texture        | the texture resources                                        |
| utils          | Interfaces of mobile(exported from external) and other tests |
| others         | default configuration files by npm and yarn                  |

### The Implemented Requirement

Generally we import most of the render effect such as shade，water and tile render from other developers‘ work（The render effect is not written by us).

We focus on some specific content and finish the following requirement.

#### The authentic flying control：

We focus on the fly controls of the aircraft such as accelerating , turning and rolling. The view can be updated in real time based on the motion of  the aircraft.

**Demo:**

![](.\img\controls_2.gif)

**Realization:**

```react
export default function FlyControls (object, domElement, nipple, pointer) {
  this.object = object
  this.domElement = (domElement !== undefined) ? domElement : document
  if (domElement) this.domElement.setAttribute('tabindex', -1)

  this.movementSpeed = 0.1
  this.rollSpeed = 0.001

  this.dragToLook = false
  this.autoForward = false

      ...

  this.acceleration = 60
  this.velocity = new Vector3(0, 0, 0)

    //获得鼠标光标对象
  this.pointer = pointer
  if (this.pointer) {
    const pointerElement = document.getElementById('pointer')
    this.zone = 400
    this.pointer.on('attain', movements => {
      //获得屏幕的大小
      const dims = this.getContainerDimensions().size
      pointerElement.style.left = dims[0] / 2 + 'px'
      pointerElement.style.top = dims[1] / 2 + 'px'

      let pointerVector = new Vector2(0, 0)

      movements.on('data', move => {
        pointerVector.add(new Vector2(move.dx, move.dy))
        // 如果飞机超出区域，则自动扩大区域
        if (pointerVector.length() > this.zone) {
          pointerVector.normalize().multiplyScalar(this.zone)
        }
        pointerElement.style.transform = `
          translateX(${pointerVector.x - 16}px)
          translateY(${pointerVector.y - 16}px)
        `
        //鼠标移动敏感度
        this.mousemove({
          pageX: (pointerVector.x) / 1.5,
          pageY: (pointerVector.y) / 1.5
        })
      })
      movements.on('close', function () {
      })
    })
  }

    ...

    //表示向量的旋转
  this.tmpQuaternion = new Quaternion()

  this.moveState = {
    up: 0,
    down: 0,
    left: 0,
    right: 0,
    forward: 0,
    back: 0,
    pitchUp: 0,
    pitchDown: 0,
    yawLeft: 0,
    yawRight: 0,
    rollLeft: 0,
    rollRight: 0
  }
  this.moveVector = new Vector3(0, 0, 0)
  this.rotationVector = new Vector3(0, 0, 0)

    //监听鼠标事件

    ...

    //在鼠标按下（this.keydown）也会调用以下函数
  this.keyup = function (event) {
    switch (event.keyCode) {
      case 16: /* shift */ this.movementSpeedMultiplier = 1; break

      case 87: /* W */ this.moveState.forward = 0; break
      case 83: /* S */ this.moveState.back = 0; break
      case 65: /* A */ this.moveState.yawLeft = 0; break
      case 68: /* D */ this.moveState.yawRight = 0; break

      case 82: /* R */ this.moveState.up = 0; break
      case 70: /* F */ this.moveState.down = 0; break
      case 38: /* up */ this.moveState.pitchUp = 0; break
      case 40: /* down */ this.moveState.pitchDown = 0; break

      case 37: /* left */ this.moveState.yawLeft = 0; break
      case 39: /* right */ this.moveState.yawRight = 0; break

      case 81: /* Q */ this.moveState.rollLeft = 0; break
      case 69: /* E */ this.moveState.rollRight = 0; break

      default:
    }

    this.updateMovementVector()
    this.updateRotationVector()
  }

  this.mousemove = function (event) {
      //获得屏幕一半大小
    var container = this.getContainerDimensions()
    var halfWidth = container.size[ 0 ] / 2
    var halfHeight = container.size[ 1 ] / 2

    // 通过屏幕和鼠标位置计算偏角，确定飞机接下来该往哪里飞
    this.moveState.yawLeft = -event.pageX / halfWidth
    this.moveState.rollLeft = this.moveState.yawLeft / 2 - this.object.rollAngle / 5
    this.moveState.pitchDown = event.pageY / halfHeight
  }

  this.deltaVelocity = null
  this.deltaPosition = null

    //update 是执行velocity（速度向量）更新的具体操作，在内部为velocity分发了事件
    this.update = (delta) => {
    var rotMult = delta * this.rollSpeed
    this.deltaVelocity = this.moveVector.clone().multiplyScalar(
      delta / 1000 * this.acceleration
    )
    this.velocity.sub(
      this.velocity.clone().multiplyScalar(
        Math.max(
          1,
          this.deltaVelocity.length() ? 1 : 100 / (this.velocity.length() + 1)
        ) * 0.01 * delta / 16.67
      )
    ).add(this.deltaVelocity)

        ...

    this.tmpQuaternion.set(this.rotationVector.x * rotMult, this.rotationVector.y * rotMult, this.rotationVector.z * rotMult, 1).normalize()
    this.object.quaternion.multiply(this.tmpQuaternion)

    this.object.rotation.setFromQuaternion(this.object.quaternion, this.object.rotation.order)

    this.updateRotationVector()
    this.updateMovementVector()
  }

  this.updateMovementVector = function () {
    // 重新设置移动向量
    var forward = (this.moveState.forward || (this.autoForward && !this.moveState.back)) ? 1 : 0
    this.moveVector.x = (-this.moveState.left + this.moveState.right)
    this.moveVector.y = (-this.moveState.down + this.moveState.up)
    this.moveVector.z = (-forward + this.moveState.back)

  }
    //重新设置旋转向量
  this.updateRotationVector = function () {
    this.rotationVector.x = (-this.moveState.pitchDown + this.moveState.pitchUp)
    this.rotationVector.y = (-this.moveState.yawRight + this.moveState.yawLeft)
    this.rotationVector.z = (-this.moveState.rollRight + this.moveState.rollLeft)
  }

    ...

 function bind (scope, fn) {
    return function () {
      fn.apply(scope, arguments)
    }
  }
   //绑定键盘按键并添加到桌面对象
  var _keydown = bind(this, this.keydown)//=this.keydown.apply(this,arguments)
  var _keyup = bind(this, this.keyup)

  window.addEventListener('keydown', _keydown, false)
  window.addEventListener('keyup', _keyup, false)

  this.updateMovementVector()
  this.updateRotationVector()
};
```

#### Two types of shooting

We realize two kinds of weapon —— bullet and missile.

Realization:

**Demo:**

![](.\img\fire.gif)

**Realization:**

```react
import {camera, renderer, scene} from "../index";
import PubSub from "../events";
import keyboardJS from "keyboardjs";
import {Mesh, MeshPhongMaterial, SphereBufferGeometry} from "three";
import {hudElement, selectNearestTargetInSight} from "../hud";
import {triggerExplosion} from "../particles";

const fireControls = (pilotDrone,controls) => {
    keyboardJS.bind('c', e => {
        console.log(camera.position)
    })
    keyboardJS.bind('r', e => {
        if (controls.module.constructor.name === 'OrbitControls') {
            controls.module.autoRotate = !controls.module.autoRotate
        }
    })
    keyboardJS.bind('space', e => PubSub.publish('x.toggle.play'))
    // 设置子弹的大小材质 ，半径，水平线段数，垂直线段数
    const bullet = new Mesh(
        new SphereBufferGeometry(1, 5, 5),
        new MeshPhongMaterial({color: 0x111111})
    )

    //开火
    const fireBullet = e => {
        if (!pilotDrone) return

        if (e.button === 0) {
            // 左键正常子弹
            PubSub.publish('x.drones.gun.start', pilotDrone)
            PubSub.publish('x.camera.shake.start', 5)
            pilotDrone.gunClock.start()
        } else if (e.button === 2) {
            // 右键发射导弹,导弹在一定范围内有追踪功能，所以是selectNearestTargetInSight
            const target = selectNearestTargetInSight()
            if (target === null || target.destroyed) return
            // bullet.clone()
            const fire = new Mesh(
                new SphereBufferGeometry(5, 32, 32),
                new MeshPhongMaterial({color: 0x111111})
            )
            fire.position.copy(pilotDrone.position)
            scene.add(fire)
            PubSub.publish('x.drones.missile.start', fire)

            //导弹构建
            const BulletContructor = function () {
                this.alive = true
                this.object = fire
                this.loop = (timestamp, delta) => {
                    if (!this.alive) return
                    const vec = target.position.clone().sub(fire.position)
                    if (vec.length() < 10) {
                        this.alive = false
                        triggerExplosion(target)
                        //分发事件
                        PubSub.publish('x.drones.missile.stop', fire)
                        PubSub.publish('x.drones.explosion', target)
                        // 打中一次扣掉25滴生命
                        target.userData.life -= 25
                        hudElement.forceUpdate()
                    }
                    // 导弹前进
                    const newDir = vec.normalize().multiplyScalar(10 * delta / 16.66)
                    fire.position.add(newDir)
                }
            }
            const callback = new BulletContructor()
            // 将导弹加入到全局loop动画更新中
            PubSub.publish('x.loops.push', callback)
        }
    }
    renderer.domElement.addEventListener('mousedown', fireBullet,false)
    renderer.domElement.addEventListener('mouseup', (e) => {
        if (e.button === 0) {
            PubSub.publish('x.drones.gun.stop', pilotDrone)
            PubSub.publish('x.camera.shake.stop')
            pilotDrone.gunClock.stop()
        }
    }, false)
}
export default fireControls
```

#### The adjustable battlefield

We can adjust the environment through the panal on the upright of the scream.

**Demo:**

![](.\img\environ_2.gif)

#### The complete game procedure

Along from the 3d effects, we present the user with the complete game procedure from begin to end.

**Demo:**

![](.\img\phase.gif)

### Advantage and Disadvantage

**Advantage：**

+ The simulation of the air war is quite real，with the exciting effect of explosion, terrain from SPE open source package.
+ The map is requested on-line. It doesn't need to be loaded at once and it's quite high-quality.
+  We try to use Three.js and React  rather than Unity. It is the first time we make the 3d game with Javascript on the web.
+ We can change the environment of battlefield.

**Disadvantage:**

+ Because this game is on web, there is a need to check the user's browser and do unit tests. it takes us much time to understand how to combine Three.js with React. Also we need to code more in comparison to using Unity.

+ The game's loading is a little slow and the flying is not smooth.

+ Because the model of the plane is actually a sphere, the detection of crashing is not true.

+ Though the requested map in real time is delicate, the external API makes the game slower.

+ You can not choose the plane and weapon.

### How to improve（one to one）

+ If we learn to use Redux and other data management tools, we can abandon the general PubSub. It will make the logic of the game more clear (certainly Redux is more difficult ).

+ Use the mouse to replace 'Q' and 'E', if the turning angle is larger than is specific point (like ＞ 60°)，the plane will automatically roll. This will relieve the load of keyboard event listener.

+ Use other geometry to new the object. For example `new PolyhedronGeometry(vertices,faces,radius,details)` is much better than the original

  `new SphereGeometry(radius,widthSegments,heightSegments)`，however this makes the crash detection quite complex and we can not finish it.

+ Load the map off-line with limited size.

+ Make more planes and weapons with various appearances and attributes.

repository: Greilfang/Air-War

path: /Air War HCI/document.md

gha_language: JavaScript

repo_name: Greilfang/Air-War


text:
---
layout: creature
name: "Mimi"
tags: [tiny, fey, cr2, tome-of-horrors]
cha: 14 (+2)
wis: 13 (+1)
int: 15 (+2)
con: 14 (+2)
dex: 19 (+4)
str: 4 (-3)
size: Tiny fey
alignment: neutral good
challenge: "2 (450 XP)"
languages: "Common, Sylvan"
skills: "Perception +3, Stealth +6 (+8 in snowy terrain)"
senses: "darkvision 60 ft., passive Perception 11"
damage_immunities: "cold"
speed: "10 ft., fly 50 ft."
hit_points: "9 (2d4 + 4)"
armor_class: "14"
---

***Group Casting (1/day).*** A group of three or more mimis together can
use freezing sphere.

***Magic Resistance.*** The mimi has advantage on saving throws against
spells and other magic effects.

***Innate Spellcasting.*** The mimi’s spellcasting ability is Charisma (spell
save DC 12, +4 to hit with spell attacks). It can innately cast the following
spells, requiring no material components:

* At will: invisibility, ray of frost

* 2/day: frost fingers (as burning hands, but cold damage)

* 1/day: cone of cold

### Actions

***Shortsword.*** Melee Weapon Attack: +6 to hit, reach 5 ft., one target.
Hit: 7 (1d6 + 4) piercing damage.

***Lower Temperature.*** The mimi lowers the temperature in an area within
30 feet of it that is no larger than a 15-foot cube. Creatures who enter or
begin their turn within the area must succeed on a DC 12 Constitution
saving throw or take 11 (2d8 + 2) cold damage. If a creature takes cold
damage, it has disadvantage on all attack rolls and ability checks for 1
minute.

gha_language: CSS

gha_license_id: NOASSERTION


text:
launchers
=========

launchers is a collection of basic tool-launching batch and shell scripts for use on Windows
machines, primarily targed at providing easy integration with Unix-world tools like `git`, `vim`,
and `bash`.

Description
===========

These scripts are intended to live in a single directory that is itself part of the path. They
provide a set of launchers that can be referenced in typical tool configuration files such as
`.gitconfig` that circumvent some Windows idiosyncracies (such as spotty support for redirection)
while allowing a single directory to be added to the system `%PATH%` (a la `/usr/bin`) instead of
requiring each individual tool's directory to be appended.

Minimum Requirements
====================

* Microsoft Windows (http://www.microsoft.com)
* GNU bash 3.1 or greater (typically installed with git; http://git-scm.com)
* Various tools referenced by the scripts

I've tested these scripts using Windows 7 64-bit and **nothing else**.

Installation
============

Simply clone the repository into a single directory on your drive, then add that directory to either
the system path or the user-specific path. There should be plenty of online documentation describing
this process.

Tests
=====

No tests of any kind are provided with the distribution at this time.

Uninstallation
==============

To uninstall the launchers, simply remove the install directory from your drive, then remove that
directory from both the system path and the user-specific path. There should be plenty of online
documentation describing this process.

Improvements
============

There are a few things I'd like to do:

* It might be nice not to need a shell script and a batch file for the same launcher when it must
  be used from both the command line and from, for example, a `git` configuration file.

Author
======

Jon Speicher ([jon.speicher@gmail.com](mailto:jon.speicher@gmail.com))

License
=======

See the file `LICENSE` included with this repository.

repository: jonspeicher/launchers

branch_name: refs/heads/main

extension: markdown

repo_name: jonspeicher/launchers


text:
---
title: "Schema"
date: 2021-02-16T11:39:08+01:00
draft: false
weight: 2
pre: "<b>3.2 </b>"
---
So now that we know our Active Directory can contain Donkeys, Ogre's, Dragons and Castles we can talk about the Active Directory Schema. The schema of Active Directory defines the rules how a object class looks like, what attributes are mandatory and are which ones optional.  The schema itself is shared between all the domains (and tree's) in Active Directory (forest).

![](blueprint.png)


text:
---
date: 2016-01-17
title: Chronyd and SELINUX
category: OSS
tags:
- linux
- chrony
- selinux
- fedora
- fc22
layout: post
published: true
---
{% include JB/setup %}

This is a small thing : ```chrony``` seemed to have lost track of time,
the fix was simple - and had to do with ```SELINUX```.

### Losing Track of Time

The clock on my machine seemed unusually 'off'.  My first comparison was to my mobile phone
- an easy check, since mobiles are typically synced against the mobile-provider / cell towers.

Checking as to the state of play on the machine itself :

{% highlight bash %}
systemctl status chronyd
## reports a normal-looking status (running, and enabled)
chronyc sourcestats
## reports Zero sources...  Something is up
{% endhighlight %}

### Where are the sources?

The default Fedora ```/etc/chrony.conf``` contains a valid 'pool' configuration :

{% highlight bash %}
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
pool 2.fedora.pool.ntp.org iburst

#....
{% endhighlight %}

so why are no sources picked up?  Checking ```/var/log/messages``` shows  :

{% highlight bash %}
Jan 17 02:09:07 square kernel: audit: type=1400 audit(1452967747.816:791): \
  avc:  denied  { read } for  pid=12887 comm="chronyd" name="resolv.conf" dev="sdb1" \
  ino=3425971 scontext=system_u:system_r:chronyd_t:s0 \
  tcontext=unconfined_u:object_r:user_home_t:s0 \
  tclass=file permissive=0
{% endhighlight %}

This tells us that ```chronyd``` is being denied something by ```SELINUX``` (something
that I felt sure I had turned to ```permissive mode```, since it's often a source of
hard-to-fathom errors).

### Bug in chronyd?

At first blush, this seemed like an error with ```chronyd```, since the rest of the
system was working fine.

However, ```SELINUX``` is doing a typical mis-direct here : The problem actually
lay with the ```/etc/resolv.conf``` file itself - it had somehow become *mislabled*.

### Simple Fix

{% highlight bash %}
## Relabel (SELINUX-wise) the file in question
restorecon -v /etc/resolv.conf

## Restart chronyd to force it to retry accessing the file
systemctl restart chronyd

## Check that chronyd now has a non-zero 'Number of sources'
chronyc sourcestats

210 Number of sources = 4
Name/IP Address            NP  NR  Span  Frequency  Freq Skew  Offset  Std Dev
==============================================================================
<IP_ADDRESS>.static.m1  17  13   43m     +1.256      0.300  +6034us   210us
ntp01.cosmicflu.com        17   9   31m     +0.152      0.216  +7966us   129us
time1.maxonline.com.sg      0   0     0     +0.000   2000.000     +0ns  4000ms
unknown.maxonline.com.sg   15   6   35m     +1.158      6.231  -6320us  3137us
{% endhighlight %}

Solved.


text:
# Setup
* configure .full-build in user home
* setup a git or mercurial master repository
* setup a binary share using appropriate security :
  * CI must be able to write to this share and is the only trusted client
  * Developers should have only readonly access to binary share

# Before going on
It is useful to recall full-build does use a central binary repository to allow partial builds.
This puts some contraints on the way you build your projects. There are two point of attention as everything ends up in the same folder (more precisely workspace/bin) you have to ensure copy'ed files do not get overriden accross project.

# Configure from scratch
## master repository
First of all, create an empty repository (either Git or Mercurial). This will be the master repository.
Ensure developpers have read access. Allow write access to people in charge of configuration.

# ssh keys
TO DO

## master artifacts
Then create a public share. Full build artifacts will be pushed there and should be available to anyone.
Ensure developpers have read access. Allow write access to people in charge of configuration (including CI).

## anthology configuration
An anthology is the term used in full-build to describe the universe of projects, nugets and assemblies. full-build tracks everything is order to allow you to create smaller build based on the full build.

Create a new workspace using command:
  fullbuild setup <local folder> <master repository> <master artifacts>

Under <local folder>, full-build has initialized everything to start a new anthology configuration from scratch.
Now, you can start adding external repositories. They have to be converted later to be compatible with full-build.

Add a new repository using command:
  fullbuild add repo <name> <url>

<name> is the nickname you want to set for your repository.
<url> is where your repository can be found

Now clone your repository before converting:
  fullbuild clone <name>

<name> is a wildcard (* supported)

A moment later, all sources are cloned. It is time to convert to full-build using command:
  fullbuild convert

If everything is ok, you have now successfuly added projects to the anthology.
You can now start building and check if everything is ok:
  fullbuild add view add *
  fullbuild build all

Eventually commit & push everything:
  fullbuild push

# How to configure Continuous Integration for full build
CI role is to build all sources.

Following steps must be orchestrated on CI:
* clone master repository (fullbuild init <folder> <master repository>)
* cd <folder>
* clone all respositories using full-build (fullbuild clone *)
* generate a view with all sources (fullbuild add view all *)
* build all sources (fullbuild build all)
* generate a new version (fullbuild fullbuild push)

# Partial build
Developer environment or CI partial build

* clone master repository (fullbuild init <folder> <master repository>)
* cd <folder>
* clone required repositories (fullbuild clone <repoName>)
* build a view with all sources (fullbuild add view mypartialview *)
* build all sources (fullbuild build mypartialview)

repository: full-build/full-build

gha_language: F#

repo_name: full-build/full-build


text:
---
ID: 3443
post_title: >
  How to continue a for each loop
  container in SSIS, when inner tasks
  fail.
author: Roel van Lisdonk
post_excerpt: ""
layout: post
permalink: >
  https://www.roelvanlisdonk.nl/2013/09/17/how-to-continue-a-for-each-loop-container-in-ssis-when-inner-tasks-fail/
published: true
post_date: 2013-09-17 13:31:00
---

If you want to continue a for each loop container in SSIS, when an inner task fails, you van follow the steps at:

http://www.codeproject.com/Articles/384690/In-SSIS-how-to-continue-a-for-each-loop-container

repository: roelvanlisdonk/blogposts

repo_name: roelvanlisdonk/blogposts


text:
---
title: |
    402. Thy Word Is Like a Garden - Christ in Song
metadata:
    description: |
        Christ in Song 402. Thy Word Is Like a Garden. Thy Word is like a garden, Lord, With flowers bright and fair; And ev'ry one who seeks may pluck And weave a garland rare.
    keywords:  |
        Christ in Song, adventhymnals, advent hymnals, Thy Word Is Like a Garden, Thy Word is like a garden, Lord.
    author: Brian Onang'o
---

#### Advent Hymnals
## 402. THY WORD IS LIKE A GARDEN
####  Christ in Song,

```txt
1.
Thy Word is like a garden, Lord,
With flowers bright and fair;
And ev'ry one who seeks may pluck
And weave a garland rare.

2.
Thy Word is like a deep, deep  mine;
And jewels rich and rare
Are hidden in its mighty depths
For ev'ry searcher there.

3.
O may I love Thy precious Word,
May I explore the mine,
May I the fragrant flowers glean,
Thy graces all divine.

```

- |   -  |
-------------|------------|
Title | Thy Word Is Like a Garden |
Key | B♭ Major |
Titles | undefined |
First Line | Thy Word is like a garden, Lord |
Author | E. Hodder
Year | 1908
Composer| undefined |
Hymnal|  - |
Tune| TIVERTON |
Metrical pattern | |
# Stanzas |  |
Chorus |  |
Chorus Type |  |
Subjects | God: God's Word |
Texts | undefined |
Print Texts |
Scripture Song |  |

repository: GospelSounders/adventhymnals

repo_name: GospelSounders/adventhymnals


text:
# Gatech-CS6750 Human-Computer Interaction (HCI)

Course Link: https://www.omscs.gatech.edu/cs-6750-human-computer-interaction

Course Page: https://omscs6750.gatech.edu/

Udacity
https://classroom.udacity.com/courses/ud400/

OMS Central: https://omscentral.com/course/CS-6750

Ref Repo:
- https://github.com/manikandan-ravikiran/HCI_Notes
- https://github.com/jgajera/CS6750-Human-Computer-Interaction


text:
nn-episode2
===========

Implementation of a sliding menu in android following the tutorial over at [Android Hive](http://www.androidhive.info/2013/11/android-sliding-menu-using-navigation-drawer/).

Things that might prove useful later on.

1. IDE used was [Android Studio](http://developer.android.com/sdk/installing/studio.html)
2. [GenyMotion emulator](http://www.genymotion.com/) (Personal use license). I would definitely recommend you use this. Setup information can be found [here](https://cloud.genymotion.com/page/launchpad/download/). You need to register an account to access it.
3. Build settings can be found at [app/build.gradle](https://github.com/jibiabraham/nn-episode2/blob/master/app/build.gradle)
4. Resources have been included in the repo.

Screenshots
===========
![Image](/screenshots/s1.png)
![Image](/screenshots/s2.png)
![Image](/screenshots/s3.png)
![Image](/screenshots/s4.png)


text:
EvilPlanner [![Status Zero][status-zero]][andivionian-status-classifier]
===========

**NOTE:** the project has been merged into [fornever.me][].

EvilPlanner is a small lab application.

Features
--------

Currently it will only output the random quote from Evil Overlord List (see
quotation source for every quote near the quote itself).

Database Setup
--------------

EvilPlanner uses LiteDB for data storage. It will migrate its databases
automatically if necessary.

Configuration
-------------

Change `EvilPlanner.Backend/appsettings.json` file to change the application
settings.

You'll probably want to change `databasePath` parameter and point it to a
preferred location for the database.

Build
-----

You may compile the code using .NET Core SDK:

```console
$ dotnet build -c Release
```

Deployment
----------

To deploy the project, check the `docker-compose.yml` and run the following
script:

```
$ pwsh ./docker-compose.ps1
```

[andivionian-status-classifier]: https://github.com/ForNeVeR/andivionian-status-classifier#status-zero-
[fornever.me]: https://github.com/ForNeVeR/fornever.me
[status-zero]: https://img.shields.io/badge/status-zero-lightgrey.svg

repository: ForNeVeR/EvilPlanner

repo_name: ForNeVeR/EvilPlanner


text:
# Journal

#### By _**Nicole Sanders, Caitlin Hines**_

## Description

This program will display the word count and vowel count of a journal entery as well as displays the first line of the entry.

## Setup/Installation Requirements

* Clone this repository
* Install npm by writing npm init in the command line
* Install bower by writing bower init in the command line
* In the command line run npm install
* In the command line run bower install
* In the command line run gulp build
* In the command line run gulp serve

## Known Bugs

There are no known bugs. Please contact us if any are discovered.

## Support and contact details

Contact Nicole Sanders at<EMAIL_ADDRESS>for any questions, comments, or concerns.

## Technologies Used

* NPM
* Bower
* JavaScript

### License

*This software is licensed under the MIT license*

Copyright (c) 2017 **_Nicole Sanders, Caitlin Hines_**


text:
# ServNode---Basic-nodeJs-server
ServNode is a basic nodeJs server using expressJs and mongoDb.

# To use the server
  1. Download the source
  2. run `npm i` inside the root folder.
  3. Make sure that your MongoDb daemon is running on 27017 port
  4. run `npm run serve` indide the root folder // this will start server which will listen on localhost:3000